forked from extern/Unexpected-Keyboard
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.
This commit is contained in:
parent
7462955507
commit
31d6a70dfb
@ -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<String> extra_keys; // 'null' means all the keys
|
||||
public Set<KeyValue> 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<String> extra_keys = new HashSet<String>(this.extra_keys);
|
||||
final Set<KeyValue> extra_keys = new HashSet<KeyValue>(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<String> extra_keys_it = extra_keys.iterator();
|
||||
kw = kw.addExtraKeys(
|
||||
new Iterator<KeyValue>()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -7,11 +7,8 @@ import java.util.HashMap;
|
||||
class KeyModifier
|
||||
{
|
||||
/** Cache key is KeyValue's name */
|
||||
private static HashMap<String, HashMap<Pointers.Modifiers, KeyValue>> _cache =
|
||||
new HashMap<String, HashMap<Pointers.Modifiers, KeyValue>>();
|
||||
|
||||
/** Represents a removed key, because a cache entry can't be [null]. */
|
||||
private static final KeyValue removed_key = KeyValue.getKeyByName("removed");
|
||||
private static HashMap<KeyValue, HashMap<Pointers.Modifiers, KeyValue>> _cache =
|
||||
new HashMap<KeyValue, HashMap<Pointers.Modifiers, KeyValue>>();
|
||||
|
||||
/** 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<Pointers.Modifiers, KeyValue> cacheEntry(KeyValue k)
|
||||
{
|
||||
HashMap<Pointers.Modifiers, KeyValue> ks = _cache.get(k.name);
|
||||
HashMap<Pointers.Modifiers, KeyValue> ks = _cache.get(k);
|
||||
if (ks == null)
|
||||
{
|
||||
ks = new HashMap<Pointers.Modifiers, KeyValue>();
|
||||
_cache.put(k.name, ks);
|
||||
_cache.put(k, ks);
|
||||
}
|
||||
return ks;
|
||||
}
|
||||
|
@ -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<String, KeyValue> keys = new HashMap<String, KeyValue>();
|
||||
|
||||
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.
|
||||
|
@ -80,19 +80,19 @@ public class Keyboard2 extends InputMethodService
|
||||
_currentTextLayout = l;
|
||||
}
|
||||
|
||||
private void extra_keys_of_subtype(Set<String> dst, InputMethodSubtype subtype)
|
||||
private void extra_keys_of_subtype(Set<KeyValue> 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<String> extra_keys = new HashSet<String>();
|
||||
HashSet<KeyValue> extra_keys = new HashSet<KeyValue>();
|
||||
List<InputMethodSubtype> 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<String>(); break;
|
||||
case 4: _config.extra_keys = new HashSet<KeyValue>(); break;
|
||||
}
|
||||
// Fallback for the layout option: Use qwerty in the "system settings" case
|
||||
_currentTextLayout = (_config.layout == -1) ? R.xml.qwerty : _config.layout;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user