mirror of
https://github.com/Julow/Unexpected-Keyboard.git
synced 2025-08-18 15:49:02 +02:00
Add complex keys (#774)
This allows to add new kinds of keys that need more data without making KeyValue's footprint bigger for common keys. This changes the [_symbol] field into [_payload], which holds the same as the previous field for more common keys but can hold bigger objects for keys of the new "Complex" kind. This also adds a complex key: String keys with a symbol different than the outputted string. Unit tests are added as the Java language is not helpful in making robust code.
This commit is contained in:
@@ -91,7 +91,8 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
{
|
||||
Char, String, Keyevent, Event, Compose_pending, Hangul_initial,
|
||||
Hangul_medial, Modifier, Editing, Placeholder,
|
||||
Cursor_move // Value is encoded as a 16-bit integer
|
||||
Cursor_move, // Value is encoded as a 16-bit integer.
|
||||
Complex, // [_payload] is a [KeyValue.Complex], value is [Complex.Kind].
|
||||
}
|
||||
|
||||
private static final int FLAGS_OFFSET = 19;
|
||||
@@ -129,7 +130,13 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
check((((Kind.values().length - 1) << KIND_OFFSET) & ~KIND_BITS) == 0);
|
||||
}
|
||||
|
||||
private final String _symbol;
|
||||
/**
|
||||
* The symbol that is rendered on the keyboard as a [String].
|
||||
* Except for keys of kind:
|
||||
* - [String], this is also the string to output.
|
||||
* - [Complex], this is an instance of [KeyValue.Complex].
|
||||
*/
|
||||
private final Object _payload;
|
||||
|
||||
/** This field encodes three things: Kind, flags and value. */
|
||||
private final int _code;
|
||||
@@ -153,7 +160,9 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
When [getKind() == Kind.String], also the string to send. */
|
||||
public String getString()
|
||||
{
|
||||
return _symbol;
|
||||
if (getKind() == Kind.Complex)
|
||||
return ((Complex)_payload).getSymbol();
|
||||
return (String)_payload;
|
||||
}
|
||||
|
||||
/** Defined only when [getKind() == Kind.Char]. */
|
||||
@@ -211,25 +220,32 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
return (short)(_code & VALUE_BITS);
|
||||
}
|
||||
|
||||
/** Defined only when [getKind() == Kind.Complex]. */
|
||||
public Complex getComplex()
|
||||
{
|
||||
return (Complex)_payload;
|
||||
}
|
||||
|
||||
/** Defined only when [getKind() == Kind.Complex]. */
|
||||
public Complex.Kind getComplexKind()
|
||||
{
|
||||
return Complex.Kind.values()[(_code & VALUE_BITS)];
|
||||
}
|
||||
|
||||
/* Update the char and the symbol. */
|
||||
public KeyValue withChar(char c)
|
||||
{
|
||||
return new KeyValue(String.valueOf(c), Kind.Char, c, getFlags());
|
||||
}
|
||||
|
||||
public KeyValue withSymbol(String s)
|
||||
{
|
||||
return new KeyValue(s, (_code & KIND_BITS), (_code & VALUE_BITS), getFlags());
|
||||
}
|
||||
|
||||
public KeyValue withKeyevent(int code)
|
||||
{
|
||||
return new KeyValue(_symbol, Kind.Keyevent, code, getFlags());
|
||||
return new KeyValue(getString(), Kind.Keyevent, code, getFlags());
|
||||
}
|
||||
|
||||
public KeyValue withFlags(int f)
|
||||
{
|
||||
return new KeyValue(_symbol, (_code & KIND_BITS), (_code & VALUE_BITS), f);
|
||||
return new KeyValue(getString(), (_code & KIND_BITS), (_code & VALUE_BITS), f);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -247,7 +263,9 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
d = _code - snd._code;
|
||||
if (d != 0)
|
||||
return d;
|
||||
return _symbol.compareTo(snd._symbol);
|
||||
if (getKind() == Kind.Complex)
|
||||
return ((Complex)_payload).compareTo((Complex)snd._payload);
|
||||
return ((String)_payload).compareTo((String)snd._payload);
|
||||
}
|
||||
|
||||
/** Type-safe alternative to [equals]. */
|
||||
@@ -255,24 +273,36 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
{
|
||||
if (snd == null)
|
||||
return false;
|
||||
return _symbol.equals(snd._symbol) && _code == snd._code;
|
||||
return _code == snd._code && _payload.equals(snd._payload);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return _symbol.hashCode() + _code;
|
||||
return _payload.hashCode() + _code;
|
||||
}
|
||||
|
||||
public KeyValue(String s, int kind, int value, int flags)
|
||||
public String toString()
|
||||
{
|
||||
_symbol = s;
|
||||
int value = _code & VALUE_BITS;
|
||||
return "[KeyValue " + getKind().toString() + "+" + getFlags() + "+" + value + " \"" + getString() + "\"]";
|
||||
}
|
||||
|
||||
private KeyValue(Object p, int kind, int value, int flags)
|
||||
{
|
||||
_payload = p;
|
||||
_code = (kind & KIND_BITS) | (flags & FLAGS_BITS) | (value & VALUE_BITS);
|
||||
}
|
||||
|
||||
public KeyValue(String s, Kind k, int v, int f)
|
||||
public KeyValue(Complex p, Complex.Kind value, int flags)
|
||||
{
|
||||
this(s, (k.ordinal() << KIND_OFFSET), v, f);
|
||||
this((Object)p, (Kind.Complex.ordinal() << KIND_OFFSET), value.ordinal(),
|
||||
flags);
|
||||
}
|
||||
|
||||
public KeyValue(String p, Kind k, int v, int f)
|
||||
{
|
||||
this(p, (k.ordinal() << KIND_OFFSET), v, f);
|
||||
}
|
||||
|
||||
private static KeyValue charKey(String symbol, char c, int flags)
|
||||
@@ -397,6 +427,11 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
return KeyValue.makeCharKey((char)precomposed);
|
||||
}
|
||||
|
||||
public static KeyValue makeActionKey(String symbol)
|
||||
{
|
||||
return eventKey(symbol, Event.ACTION, FLAG_SMALLER_FONT);
|
||||
}
|
||||
|
||||
/** Make a key that types a string. A char key is returned for a string of
|
||||
length 1. */
|
||||
public static KeyValue makeStringKey(String str, int flags)
|
||||
@@ -407,12 +442,36 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
return new KeyValue(str, Kind.String, 0, flags | FLAG_SMALLER_FONT);
|
||||
}
|
||||
|
||||
public static KeyValue makeStringKeyWithSymbol(String str, String symbol, int flags)
|
||||
{
|
||||
return new KeyValue(new Complex.StringWithSymbol(str, symbol),
|
||||
Complex.Kind.StringWithSymbol, flags);
|
||||
}
|
||||
|
||||
/** Make a modifier key for passing to [KeyModifier]. */
|
||||
public static KeyValue makeInternalModifier(Modifier mod)
|
||||
{
|
||||
return new KeyValue("", Kind.Modifier, mod.ordinal(), 0);
|
||||
}
|
||||
|
||||
public static KeyValue parseKeyDefinition(String str)
|
||||
{
|
||||
if (str.length() < 2 || str.charAt(0) != ':')
|
||||
return makeStringKey(str);
|
||||
try
|
||||
{
|
||||
return KeyValueParser.parse(str);
|
||||
}
|
||||
catch (KeyValueParser.ParseError _e)
|
||||
{
|
||||
return makeStringKey(str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a key by its name. If the given name doesn't correspond to a key
|
||||
* defined in this function, it is passed to [parseStringKey] as a fallback.
|
||||
*/
|
||||
public static KeyValue getKeyByName(String name)
|
||||
{
|
||||
switch (name)
|
||||
@@ -599,8 +658,8 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
case "ㅍ": return makeHangulInitial("ㅍ", 17);
|
||||
case "ㅎ": return makeHangulInitial("ㅎ", 18);
|
||||
|
||||
/* Fallback to a string key that types its name */
|
||||
default: return makeStringKey(name);
|
||||
/* The key is not one of the special ones. */
|
||||
default: return parseKeyDefinition(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -610,4 +669,49 @@ public final class KeyValue implements Comparable<KeyValue>
|
||||
if (!b)
|
||||
throw new RuntimeException("Assertion failure");
|
||||
}
|
||||
|
||||
public static abstract class Complex
|
||||
{
|
||||
public abstract String getSymbol();
|
||||
|
||||
/** [compareTo] can assume that [snd] is an instance of the same class. */
|
||||
public abstract int compareTo(Complex snd);
|
||||
|
||||
public boolean equals(Object snd)
|
||||
{
|
||||
if (snd instanceof Complex)
|
||||
return compareTo((Complex)snd) == 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** [hashCode] will be called on this class. */
|
||||
|
||||
/** The kind is stored in the [value] field of the key. */
|
||||
public static enum Kind
|
||||
{
|
||||
StringWithSymbol,
|
||||
}
|
||||
|
||||
public static final class StringWithSymbol extends Complex
|
||||
{
|
||||
public final String str;
|
||||
private final String _symbol;
|
||||
|
||||
public StringWithSymbol(String _str, String _sym)
|
||||
{
|
||||
str = _str;
|
||||
_symbol = _sym;
|
||||
}
|
||||
|
||||
public String getSymbol() { return _symbol; }
|
||||
|
||||
public int compareTo(Complex _snd)
|
||||
{
|
||||
StringWithSymbol snd = (StringWithSymbol)_snd;
|
||||
int d = str.compareTo(snd.str);
|
||||
if (d != 0) return d;
|
||||
return _symbol.compareTo(snd._symbol);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user