keyboard accelerators
authorKevin Lamonte <kevin.lamonte@gmail.com>
Sat, 14 Mar 2015 21:14:12 +0000 (17:14 -0400)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Sat, 14 Mar 2015 21:14:12 +0000 (17:14 -0400)
src/jexer/TApplication.java
src/jexer/TCommand.java
src/jexer/TKeypress.java
src/jexer/bits/Cell.java
src/jexer/bits/CellAttributes.java
src/jexer/bits/Color.java
src/jexer/event/TCommandEvent.java
src/jexer/event/TKeypressEvent.java
src/jexer/menu/TMenu.java

index 35aa32d0d0f5dd4c892ab4a3ae79db949b90effe..d2b8f446c4d15a5b519f3c55bdc590d787c884a2 100644 (file)
@@ -34,8 +34,10 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import jexer.bits.CellAttributes;
 import jexer.bits.ColorTheme;
@@ -109,6 +111,11 @@ public class TApplication {
      */
     private TMenu activeMenu = null;
 
+    /**
+     * Active keyboard accelerators.
+     */
+    private Map<TKeypress, TMenuItem> accelerators;
+
     /**
      * Windows and widgets pull colors from this ColorTheme.
      */
@@ -204,6 +211,7 @@ public class TApplication {
         windows         = new LinkedList<TWindow>();
         menus           = new LinkedList<TMenu>();
         subMenus        = new LinkedList<TMenu>();
+        accelerators    = new HashMap<TKeypress, TMenuItem>();
     }
 
     /**
@@ -394,8 +402,8 @@ public class TApplication {
     private void metaHandleEvent(final TInputEvent event) {
 
         /*
-         System.err.printf(String.format("metaHandleEvents event: %s\n",
-         event)); System.err.flush();
+        System.err.printf(String.format("metaHandleEvents event: %s\n",
+                event)); System.err.flush();
          */
 
         if (quit) {
@@ -404,16 +412,6 @@ public class TApplication {
             return;
         }
 
-        // DEBUG
-        if (event instanceof TKeypressEvent) {
-            TKeypressEvent keypress = (TKeypressEvent) event;
-            if (keypress.equals(kbAltX)) {
-                quit = true;
-                return;
-            }
-        }
-        // DEBUG
-
         // Special application-wide events -------------------------------
 
         // Abort everything
@@ -530,15 +528,16 @@ public class TApplication {
             return;
         }
 
-        /*
-         TODO
-
         if (event instanceof TKeypressEvent) {
             TKeypressEvent keypress = (TKeypressEvent) event;
+
             // See if this key matches an accelerator, and if so dispatch the
             // menu event.
             TKeypress keypressLowercase = keypress.getKey().toLowerCase();
-            TMenuItem item = accelerators.get(keypressLowercase);
+            TMenuItem item = null;
+            synchronized (accelerators) {
+                item = accelerators.get(keypressLowercase);
+            }
             if (item != null) {
                 // Let the menu item dispatch
                 item.dispatch();
@@ -550,7 +549,6 @@ public class TApplication {
                 }
             }
         }
-         */
 
         if (event instanceof TCommandEvent) {
             if (onCommand((TCommandEvent) event)) {
@@ -1126,11 +1124,13 @@ public class TApplication {
      */
     public final void addAccelerator(final TMenuItem item,
         final TKeypress keypress) {
-        /*
-         TODO
-        assert((keypress in accelerators) is null);
-        accelerators[keypress] = item;
-         */
+
+        // System.err.printf("addAccelerator: key %s item %s\n", keypress, item);
+
+        synchronized (accelerators) {
+            assert (accelerators.get(keypress) == null);
+            accelerators.put(keypress, item);
+        }
     }
 
     /**
index 62ff2bec9e22f37e09ef149c3a1ffab553e650f7..bacc6f15050294abb5b2f298d17e087afd6f43d3 100644 (file)
@@ -158,6 +158,16 @@ public class TCommand {
         return (type == that.type);
     }
 
+    /**
+     * Hashcode uses all fields in equals().
+     *
+     * @return the hash
+     */
+    @Override
+    public int hashCode() {
+        return type;
+    }
+
     public static final TCommand cmAbort      = new TCommand(ABORT);
     public static final TCommand cmExit       = new TCommand(EXIT);
     public static final TCommand cmQuit       = new TCommand(EXIT);
index 54be5d3e24b7df43bc37fb26378a5516355a6624..8143f151006af3fc656a8188d66b6d660c576802 100644 (file)
@@ -298,6 +298,25 @@ public final class TKeypress {
             && (shift == that.shift));
     }
 
+    /**
+     * Hashcode uses all fields in equals().
+     *
+     * @return the hash
+     */
+    @Override
+    public int hashCode() {
+        int A = 13;
+        int B = 23;
+        int hash = A;
+        hash = (B * hash) + (isKey ? 1 : 0);
+        hash = (B * hash) + fnKey;
+        hash = (B * hash) + (int)ch;
+        hash = (B * hash) + (alt ? 1 : 0);
+        hash = (B * hash) + (ctrl ? 1 : 0);
+        hash = (B * hash) + (shift ? 1 : 0);
+        return hash;
+    }
+
     /**
      * Make human-readable description of this TKeypress.
      *
@@ -471,16 +490,14 @@ public final class TKeypress {
     }
 
     /**
-     * Convert a keypress to lowercase.  Function keys and ctrl keys are not
-     * converted.
+     * Convert a keypress to lowercase.  Function keys and alt/ctrl keys are
+     * not converted.
      *
-     * @param key keypress to convert
      * @return a new instance with the key converted
      */
-    public static TKeypress toLower(final TKeypress key) {
-        TKeypress newKey = new TKeypress(key.isKey, key.fnKey, key.ch,
-            key.alt, key.ctrl, key.shift);
-        if (!(key.isKey) && (key.ch >= 'A') && (key.ch <= 'Z') && (!key.ctrl)) {
+    public TKeypress toLowerCase() {
+        TKeypress newKey = new TKeypress(isKey, fnKey, ch, alt, ctrl, shift);
+        if (!isKey && (ch >= 'A') && (ch <= 'Z') && !ctrl && !alt) {
             newKey.shift = false;
             newKey.ch += 32;
         }
@@ -488,16 +505,14 @@ public final class TKeypress {
     }
 
     /**
-     * Convert a keypress to uppercase.  Function keys and ctrl keys are not
-     * converted.
+     * Convert a keypress to uppercase.  Function keys and alt/ctrl keys are
+     * not converted.
      *
-     * @param key keypress to convert
      * @return a new instance with the key converted
      */
-    public static TKeypress toUpper(final TKeypress key) {
-        TKeypress newKey = new TKeypress(key.isKey, key.fnKey, key.ch,
-            key.alt, key.ctrl, key.shift);
-        if (!(key.isKey) && (key.ch >= 'a') && (key.ch <= 'z') && (!key.ctrl)) {
+    public TKeypress toUpperCase() {
+        TKeypress newKey = new TKeypress(isKey, fnKey, ch, alt, ctrl, shift);
+        if (!isKey && (ch >= 'a') && (ch <= 'z') && !ctrl && !alt) {
             newKey.shift = true;
             newKey.ch -= 32;
         }
index 3c0eb14a04a4c0969b4a778b6d54050379a2c89d..511963c28ac23c0f458addcafc56090bb7697bb8 100644 (file)
@@ -107,6 +107,21 @@ public final class Cell extends CellAttributes {
             && (ch == that.ch));
     }
 
+    /**
+     * Hashcode uses all fields in equals().
+     *
+     * @return the hash
+     */
+    @Override
+    public int hashCode() {
+        int A = 13;
+        int B = 23;
+        int hash = A;
+        hash = (B * hash) + super.hashCode();
+        hash = (B * hash) + (int)ch;
+        return hash;
+    }
+
     /**
      * Set my field values to that's field.
      *
index a3d912cc433805c2a771af156732bc06fe999d7d..d1aea2cfded151f64b7fab265f48e328afa1ebd7 100644 (file)
@@ -242,12 +242,32 @@ public class CellAttributes {
             && (backColor == that.backColor));
     }
 
+    /**
+     * Hashcode uses all fields in equals().
+     *
+     * @return the hash
+     */
+    @Override
+    public int hashCode() {
+        int A = 13;
+        int B = 23;
+        int hash = A;
+        hash = (B * hash) + (bold ? 1 : 0);
+        hash = (B * hash) + (blink ? 1 : 0);
+        hash = (B * hash) + (underline ? 1 : 0);
+        hash = (B * hash) + (reverse ? 1 : 0);
+        hash = (B * hash) + (protect ? 1 : 0);
+        hash = (B * hash) + foreColor.hashCode();
+        hash = (B * hash) + backColor.hashCode();
+        return hash;
+    }
+
     /**
      * Set my field values to that's field.
      *
      * @param rhs another CellAttributes instance
      */
-    public void setTo(Object rhs) {
+    public void setTo(final Object rhs) {
         CellAttributes that = (CellAttributes) rhs;
 
         this.bold      = that.bold;
index 707b244b12664aa04a2c691cb73cfa3973d06e27..54ae66aeaf0d54fac263e1e3445bfa47dc50ef9c 100644 (file)
@@ -215,6 +215,16 @@ public final class Color {
         return (value == that.value);
     }
 
+    /**
+     * Hashcode uses all fields in equals().
+     *
+     * @return the hash
+     */
+    @Override
+    public int hashCode() {
+        return value;
+    }
+
     /**
      * Make human-readable description of this Color.
      *
@@ -239,8 +249,9 @@ public final class Color {
             return "blue";
         case SGRYELLOW:
             return "yellow";
+        default:
+            throw new IllegalArgumentException("Invalid Color value: " + value);
         }
-        throw new IllegalArgumentException("Invalid Color value: " + value);
     }
 
 }
index fb3050b1dcc71dc2fbb99977f116f5f29dcbd616..e430dafa6d88b90e166b1e4cacacb38f3f2cfa24 100644 (file)
@@ -86,6 +86,21 @@ public final class TCommandEvent extends TInputEvent {
         return (cmd.equals(that));
     }
 
+    /**
+     * Hashcode uses all fields in equals().
+     *
+     * @return the hash
+     */
+    @Override
+    public int hashCode() {
+        int A = 13;
+        int B = 23;
+        int hash = A;
+        hash = (B * hash) + getTime().hashCode();
+        hash = (B * hash) + cmd.hashCode();
+        return hash;
+    }
+
     /**
      * Make human-readable description of this TCommandEvent.
      *
index 03c4f71e5ed510b93711887b676c89c337e764d0..bf8a51afe09ce4ec7f723a202c4dfcd12f9684e3 100644 (file)
@@ -115,6 +115,21 @@ public final class TKeypressEvent extends TInputEvent {
         return (key.equals(that));
     }
 
+    /**
+     * Hashcode uses all fields in equals().
+     *
+     * @return the hash
+     */
+    @Override
+    public int hashCode() {
+        int A = 13;
+        int B = 23;
+        int hash = A;
+        hash = (B * hash) + getTime().hashCode();
+        hash = (B * hash) + key.hashCode();
+        return hash;
+    }
+
     /**
      * Make human-readable description of this TKeypressEvent.
      *
index 75871c078d6f7d8bc98408fa896462532a0b9204..c9938084b3d47e9a1808041cefdc19a09eb1fc60 100644 (file)
@@ -351,7 +351,7 @@ public final class TMenu extends TWindow {
         for (TWidget widget: getChildren()) {
             widget.setWidth(getWidth() - 2);
         }
-        getApplication().addAccelerator(menuItem, toLower(key));
+        getApplication().addAccelerator(menuItem, key.toLowerCase());
         getApplication().recomputeMenuX();
         activate(0);
         return menuItem;