From 31d6a70dfb9c7ad3a72302bca2339f926e4593ee Mon Sep 17 00:00:00 2001 From: Jules Aguillon Date: Mon, 6 Jun 2022 00:23:45 +0200 Subject: [PATCH] Refactor: Remove KeyValue.name This makes KeyValue objects smaller. 'equals' and 'hashCode' are now implemented too. Key names are still used to recognise keys with special meaning, but not for comparing keys anymore. --- srcs/juloo.keyboard2/Config.java | 20 +-- srcs/juloo.keyboard2/Emoji.java | 6 +- srcs/juloo.keyboard2/KeyModifier.java | 177 ++++++++++++++------------ srcs/juloo.keyboard2/KeyValue.java | 44 +++++-- srcs/juloo.keyboard2/Keyboard2.java | 8 +- srcs/juloo.keyboard2/Pointers.java | 9 +- 6 files changed, 143 insertions(+), 121 deletions(-) diff --git a/srcs/juloo.keyboard2/Config.java b/srcs/juloo.keyboard2/Config.java index f2fe1b8..054fc41 100644 --- a/srcs/juloo.keyboard2/Config.java +++ b/srcs/juloo.keyboard2/Config.java @@ -47,7 +47,7 @@ final class Config public String actionLabel; // Might be 'null' public int actionId; // Meaningful only when 'actionLabel' isn't 'null' public boolean swapEnterActionKey; // Swap the "enter" and "action" keys - public Set extra_keys; // 'null' means all the keys + public Set extra_keys; // 'null' means all the keys public final IKeyEventHandler handler; @@ -151,18 +151,18 @@ final class Config { // Update the name to avoid caching in KeyModifier final KeyValue action_key = (actionLabel == null) ? null : - KeyValue.getKeyByName("action").withNameAndSymbol(actionLabel, actionLabel); + KeyValue.getKeyByName("action").withSymbol(actionLabel); // Extra keys are removed from the set as they are encountered during the // first iteration then automatically added. - final Set extra_keys = new HashSet(this.extra_keys); + final Set extra_keys = new HashSet(this.extra_keys); KeyboardData kw = original_kw.mapKeys(new KeyboardData.MapKeyValues() { public KeyValue apply(KeyValue key) { if (key == null) return null; - boolean is_extra_key = extra_keys.contains(key.name); + boolean is_extra_key = extra_keys.contains(key); if (is_extra_key) - extra_keys.remove(key.name); + extra_keys.remove(key); int flags = key.getFlags(); if ((flags & KeyValue.FLAG_LOCALIZED) != 0 && !is_extra_key) return null; @@ -196,15 +196,7 @@ final class Config } }); if (extra_keys.size() > 0) - { - final Iterator extra_keys_it = extra_keys.iterator(); - kw = kw.addExtraKeys( - new Iterator() - { - public boolean hasNext() { return extra_keys_it.hasNext(); } - public KeyValue next() { return KeyValue.getKeyByName(extra_keys_it.next()); } - }); - } + kw = kw.addExtraKeys(extra_keys.iterator()); return kw; } diff --git a/srcs/juloo.keyboard2/Emoji.java b/srcs/juloo.keyboard2/Emoji.java index 28c4f9f..2f00181 100644 --- a/srcs/juloo.keyboard2/Emoji.java +++ b/srcs/juloo.keyboard2/Emoji.java @@ -10,6 +10,7 @@ import java.util.HashMap; public class Emoji { + private final String _name; private final KeyValue _kv; private final String _desc; @@ -17,14 +18,15 @@ public class Emoji protected Emoji(String name, String bytecode, String desc) { - _kv = new KeyValue(name, bytecode, KeyValue.KIND_STRING, 0, 0); + _name = name; + _kv = new KeyValue(bytecode, KeyValue.KIND_STRING, 0, 0); _desc = desc; emojis_by_name.put(name, this); } public String name() { - return _kv.name; + return _name; } public KeyValue kv() diff --git a/srcs/juloo.keyboard2/KeyModifier.java b/srcs/juloo.keyboard2/KeyModifier.java index 4089ab8..fa23217 100644 --- a/srcs/juloo.keyboard2/KeyModifier.java +++ b/srcs/juloo.keyboard2/KeyModifier.java @@ -7,11 +7,8 @@ import java.util.HashMap; class KeyModifier { /** Cache key is KeyValue's name */ - private static HashMap> _cache = - new HashMap>(); - - /** Represents a removed key, because a cache entry can't be [null]. */ - private static final KeyValue removed_key = KeyValue.getKeyByName("removed"); + private static HashMap> _cache = + new HashMap>(); /** Modify a key according to modifiers. */ public static KeyValue modify(KeyValue k, Pointers.Modifiers mods) @@ -27,10 +24,10 @@ class KeyModifier /* Order: Fn, Shift, accents */ for (int i = 0; i < n_mods; i++) r = modify(r, mods.get(i)); - r = remove_placeholders(r); ks.put(mods, r); } - return (r == removed_key) ? null : r; + /* Keys with an empty string are placeholder keys. */ + return (r.getString().length() == 0) ? null : r; } public static KeyValue modify(KeyValue k, KeyValue.Modifier mod) @@ -117,70 +114,97 @@ class KeyModifier private static KeyValue apply_fn(KeyValue k) { - String name; - switch (k.name) + String name = null; + switch (k.getKind()) { - case "1": name = "f1"; break; - case "2": name = "f2"; break; - case "3": name = "f3"; break; - case "4": name = "f4"; break; - case "5": name = "f5"; break; - case "6": name = "f6"; break; - case "7": name = "f7"; break; - case "8": name = "f8"; break; - case "9": name = "f9"; break; - case "0": name = "f10"; break; - case "f11_placeholder": name = "f11"; break; - case "f12_placeholder": name = "f12"; break; - case "up": name = "page_up"; break; - case "down": name = "page_down"; break; - case "left": name = "home"; break; - case "right": name = "end"; break; - case "<": name = "«"; break; - case ">": name = "»"; break; - case "{": name = "‹"; break; - case "}": name = "›"; break; - case "[": name = "‘"; break; - case "]": name = "’"; break; - case "(": name = "“"; break; - case ")": name = "”"; break; - case "'": name = "‚"; break; - case "\"": name = "„"; break; - case "-": name = "–"; break; - case "_": name = "—"; break; - case "^": name = "¬"; break; - case "%": name = "‰"; break; - case "=": name = "≈"; break; - case "u": name = "µ"; break; - case "a": name = "æ"; break; - case "o": name = "œ"; break; - case "esc": name = "insert"; break; - case "*": name = "°"; break; - case ".": name = "…"; break; - case ",": name = "·"; break; - case "!": name = "¡"; break; - case "?": name = "¿"; break; - case "tab": name = "\\t"; break; - case "space": name = "nbsp"; break; - case "↖": name = "⇖"; break; - case "↑": name = "⇑"; break; - case "↗": name = "⇗"; break; - case "←": name = "⇐"; break; - case "→": name = "⇒"; break; - case "↙": name = "⇙"; break; - case "↓": name = "⇓"; break; - case "↘": name = "⇘"; break; - // Currency symbols - case "e": name = "€"; break; - case "l": name = "£"; break; - case "r": name = "₹"; break; - case "y": name = "¥"; break; - case "c": name = "¢"; break; - case "p": name = "₱"; break; - case "€": case "£": return removed_key; // Avoid showing these twice - default: return k; + case Char: name = apply_fn_char(k.getChar()); break; + case Keyevent: name = apply_fn_keyevent(k.getKeyevent()); break; + case String: + switch (k.getString()) + { + case "": + if (k == KeyValue.getKeyByName("f11_placeholder")) + name = "f11"; + else if (k == KeyValue.getKeyByName("f12_placeholder")) + name = "f12"; + break; + } + break; + } + return (name == null) ? k : KeyValue.getKeyByName(name); + } + + private static String apply_fn_keyevent(int code) + { + switch (code) + { + case KeyEvent.KEYCODE_DPAD_UP: return "page_up"; + case KeyEvent.KEYCODE_DPAD_DOWN: return "page_down"; + case KeyEvent.KEYCODE_DPAD_LEFT: return "home"; + case KeyEvent.KEYCODE_DPAD_RIGHT: return "end"; + case KeyEvent.KEYCODE_ESCAPE: return "insert"; + default: return null; + } + } + + /** Return the name of modified key, or [null]. */ + private static String apply_fn_char(char c) + { + switch (c) + { + case '1': return "f1"; + case '2': return "f2"; + case '3': return "f3"; + case '4': return "f4"; + case '5': return "f5"; + case '6': return "f6"; + case '7': return "f7"; + case '8': return "f8"; + case '9': return "f9"; + case '0': return "f10"; + case '<': return "«"; + case '>': return "»"; + case '{': return "‹"; + case '}': return "›"; + case '[': return "‘"; + case ']': return "’"; + case '(': return "“"; + case ')': return "”"; + case '\'': return "‚"; + case '"': return "„"; + case '-': return "–"; + case '_': return "—"; + case '^': return "¬"; + case '%': return "‰"; + case '=': return "≈"; + case 'u': return "µ"; + case 'a': return "æ"; + case 'o': return "œ"; + case '*': return "°"; + case '.': return "…"; + case ',': return "·"; + case '!': return "¡"; + case '?': return "¿"; + case '↖': return "⇖"; + case '↑': return "⇑"; + case '↗': return "⇗"; + case '←': return "⇐"; + case '→': return "⇒"; + case '↙': return "⇙"; + case '↓': return "⇓"; + case '↘': return "⇘"; + // Currency symbols + case 'e': return "€"; + case 'l': return "£"; + case 'r': return "₹"; + case 'y': return "¥"; + case 'c': return "¢"; + case 'p': return "₱"; + case '€': case '£': return "removed"; // Avoid showing these twice + case '\t': return "\\t"; + case ' ': return "nbsp"; + default: return null; } - return KeyValue.getKeyByName(name); } private static KeyValue turn_into_keyevent(KeyValue k) @@ -249,25 +273,14 @@ class KeyModifier return k.withKeyevent(e); } - /** Remove placeholder keys that haven't been modified into something. */ - private static KeyValue remove_placeholders(KeyValue k) - { - switch (k.name) - { - case "f11_placeholder": - case "f12_placeholder": return removed_key; - default: return k; - } - } - /* Lookup the cache entry for a key. Create it needed. */ private static HashMap cacheEntry(KeyValue k) { - HashMap ks = _cache.get(k.name); + HashMap ks = _cache.get(k); if (ks == null) { ks = new HashMap(); - _cache.put(k.name, ks); + _cache.put(k, ks); } return ks; } diff --git a/srcs/juloo.keyboard2/KeyValue.java b/srcs/juloo.keyboard2/KeyValue.java index f91e22d..4009525 100644 --- a/srcs/juloo.keyboard2/KeyValue.java +++ b/srcs/juloo.keyboard2/KeyValue.java @@ -78,7 +78,6 @@ final class KeyValue check((FLAGS_BITS | KIND_BITS | VALUE_BITS) == ~0); // No holes } - public final String name; private final String _symbol; /** This field encodes three things: @@ -150,37 +149,49 @@ final class KeyValue /* Update the char and the symbol. */ public KeyValue withChar(char c) { - return new KeyValue(name, String.valueOf(c), KIND_CHAR, c, getFlags()); + return new KeyValue(String.valueOf(c), KIND_CHAR, c, getFlags()); } public KeyValue withString(String s) { - return new KeyValue(name, s, KIND_STRING, 0, getFlags()); + return new KeyValue(s, KIND_STRING, 0, getFlags()); } - public KeyValue withNameAndSymbol(String n, String s) + public KeyValue withSymbol(String s) { - return new KeyValue(n, s, (_code & KIND_BITS), (_code & VALUE_BITS), getFlags()); + return new KeyValue(s, (_code & KIND_BITS), (_code & VALUE_BITS), getFlags()); } public KeyValue withKeyevent(int code) { - return new KeyValue(name, _symbol, KIND_KEYEVENT, code, getFlags()); + return new KeyValue(_symbol, KIND_KEYEVENT, code, getFlags()); } public KeyValue withFlags(int f) { - return new KeyValue(name, _symbol, (_code & KIND_BITS), (_code & VALUE_BITS), f); + return new KeyValue(_symbol, (_code & KIND_BITS), (_code & VALUE_BITS), f); + } + + @Override + public boolean equals(Object obj) + { + KeyValue snd = (KeyValue)obj; + return _symbol.equals(snd._symbol) && _code == snd._code; + } + + @Override + public int hashCode() + { + return _symbol.hashCode() + _code; } private static HashMap keys = new HashMap(); - public KeyValue(String n, String s, int kind, int value, int flags) + public KeyValue(String s, int kind, int value, int flags) { check((kind & ~KIND_BITS) == 0); check((flags & ~FLAGS_BITS) == 0); check((value & ~VALUE_BITS) == 0); - name = n; _symbol = s; _code = kind | flags | value; } @@ -207,14 +218,14 @@ final class KeyValue return kv.withFlags(kv.getFlags() | FLAG_LOCALIZED); } if (name.length() == 1) - return new KeyValue(name, name, KIND_CHAR, name.charAt(0), 0); + return new KeyValue(name, KIND_CHAR, name.charAt(0), 0); else - return new KeyValue(name, name, KIND_STRING, 0, 0); + return new KeyValue(name, KIND_STRING, 0, 0); } private static void addKey(String name, String symbol, int kind, int code, int flags) { - keys.put(name, new KeyValue(name, symbol, kind, code, flags)); + keys.put(name, new KeyValue(symbol, kind, code, flags)); } private static void addCharKey(String name, String symbol, char c, int flags) @@ -238,6 +249,11 @@ final class KeyValue addKey(name, symbol, KIND_KEYEVENT, code, flags); } + private static void addPlaceholderKey(String name) + { + addKey(name, "", KIND_STRING, 0, 0); + } + static { addModifierKey("shift", "\n", // Can't write u000A because Java is stupid @@ -307,7 +323,9 @@ final class KeyValue addCharKey("space", "\r", ' ', FLAG_KEY_FONT); addCharKey("nbsp", "\u237d", '\u00a0', FLAG_KEY_FONT | FLAG_SMALLER_FONT); - addKey("removed", "", KIND_STRING, 0, 0); // Dummy key used in [KeyModifier] + addPlaceholderKey("removed"); + addPlaceholderKey("f11_placeholder"); + addPlaceholderKey("f12_placeholder"); } // Substitute for [assert], which has no effect on Android. diff --git a/srcs/juloo.keyboard2/Keyboard2.java b/srcs/juloo.keyboard2/Keyboard2.java index 32a27a8..77fc0bf 100644 --- a/srcs/juloo.keyboard2/Keyboard2.java +++ b/srcs/juloo.keyboard2/Keyboard2.java @@ -80,19 +80,19 @@ public class Keyboard2 extends InputMethodService _currentTextLayout = l; } - private void extra_keys_of_subtype(Set dst, InputMethodSubtype subtype) + private void extra_keys_of_subtype(Set dst, InputMethodSubtype subtype) { String extra_keys = subtype.getExtraValueOf("extra_keys"); if (extra_keys == null) return; String[] ks = extra_keys.split("\\|"); for (int i = 0; i < ks.length; i++) - dst.add(ks[i]); + dst.add(KeyValue.getKeyByName(ks[i])); } private void refreshAccentsOption(InputMethodManager imm, InputMethodSubtype subtype) { - HashSet extra_keys = new HashSet(); + HashSet extra_keys = new HashSet(); List enabled_subtypes = getEnabledSubtypes(imm); switch (_config.accents) { @@ -119,7 +119,7 @@ public class Keyboard2 extends InputMethodService switch (_config.accents) { case 1: case 2: case 3: _config.extra_keys = null; break; - case 4: _config.extra_keys = new HashSet(); break; + case 4: _config.extra_keys = new HashSet(); break; } // Fallback for the layout option: Use qwerty in the "system settings" case _currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout; diff --git a/srcs/juloo.keyboard2/Pointers.java b/srcs/juloo.keyboard2/Pointers.java index 7ef714b..0548b88 100644 --- a/srcs/juloo.keyboard2/Pointers.java +++ b/srcs/juloo.keyboard2/Pointers.java @@ -68,11 +68,8 @@ public final class Pointers implements Handler.Callback */ public int getKeyFlags(KeyValue kv) { - // Comparing names because the keys might have been modified. - // Physical equality works because names are never computed or shared. - String name = kv.name; for (Pointer p : _ptrs) - if (p.value != null && p.value.name == name) + if (p.value != null && p.value.equals(kv)) return p.flags; return -1; } @@ -214,7 +211,7 @@ public final class Pointers implements Handler.Callback { ptr.selected_direction = direction; KeyValue newValue = getKeyAtDirection(ptr, direction); - if (newValue != null && (ptr.value == null || newValue.name != ptr.value.name)) + if (newValue != null && (ptr.value == null || !newValue.equals(ptr.value))) { int old_flags = ptr.flags; ptr.value = newValue; @@ -253,7 +250,7 @@ public final class Pointers implements Handler.Callback if (v == null) return null; for (Pointer p : _ptrs) - if (p.key == k && p.pointerId == -1 && p.value != null && p.value.name == v.name) + if (p.key == k && p.pointerId == -1 && p.value != null && p.value.equals(v)) return p; return null; }