Skip to content

Commit

Permalink
Preferred position for locale extra_keys
Browse files Browse the repository at this point in the history
`method.xml` is now able to specify a preferred position for each extra
keys in term of an other key to which it should be placed nearby.

It's implemented for French as an example.
  • Loading branch information
Julow committed Sep 24, 2023
1 parent 66b1bdc commit d5cbcb3
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 14 deletions.
2 changes: 1 addition & 1 deletion res/xml/method.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<subtype android:label="%s" android:languageTag="es" android:imeSubtypeLocale="es_ES" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwerty_es,extra_keys=accent_aigu:á:é:í:ó:ú|accent_tilde:ñ|accent_grave|accent_trema|€"/>
<subtype android:label="%s" android:languageTag="fa" android:imeSubtypeLocale="fa_IR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="default_layout=arab_pc_ir"/>
<subtype android:label="%s" android:languageTag="fr-CH" android:imeSubtypeLocale="fr_CH" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_fr_ch,extra_keys=accent_grave:à:è:ù|accent_aigu:é|accent_circonflexe:â:ê:ô|accent_cedille:ç|accent_trema:ë:ï:ü:ÿ|€"/>
<subtype android:label="%s" android:languageTag="fr-FR" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:à:è:ù|accent_aigu:é|accent_circonflexe:â:ê:ô|accent_cedille:ç|accent_trema:ë:ï:ü:ÿ|€"/>
<subtype android:label="%s" android:languageTag="fr-FR" android:imeSubtypeLocale="fr_FR" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_azerty_fr,extra_keys=accent_grave:à:è:ù@a|accent_aigu:é@e|accent_circonflexe:â:ê:ô@e|accent_cedille:ç@c|accent_trema:ë:ï:ü:ÿ@l|€"/>
<subtype android:label="%s" android:languageTag="he" android:imeSubtypeLocale="he_IL" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=hebrew,default_layout=hebr_1_il,extra_keys=₪|€"/>
<subtype android:label="%s" android:languageTag="hi" android:imeSubtypeLocale="hi_IN" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=devanagari,default_layout=deva_inscript,extra_keys=₹"/>
<subtype android:label="%s" android:languageTag="hu" android:imeSubtypeLocale="hu_HU" android:imeSubtypeMode="keyboard" android:isAsciiCapable="true" android:imeSubtypeExtraValue="script=latin,default_layout=latn_qwertz_hu,extra_keys=accent_aigu:á:é:í:ó:ú|accent_trema:ö:ü|accent_ogonek|accent_double_aigu:ő:ű|€"/>
Expand Down
45 changes: 32 additions & 13 deletions srcs/juloo.keyboard2/ExtraKeys.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,15 @@ final static class ExtraKey
/** The key will not be added to layout that already contain all the
alternatives. */
final List<KeyValue> alternatives;
/** The key next to which to add. Might be [null]. */
final KeyValue next_to;

ExtraKey(KeyValue kv_, String script_, List<KeyValue> alts_)
ExtraKey(KeyValue kv_, String script_, List<KeyValue> alts_, KeyValue next_to_)
{
kv = kv_;
script = script_;
alternatives = alts_;
next_to = next_to_;
}

/** Whether the key should be added to the keyboard. */
Expand All @@ -86,7 +89,13 @@ public void compute(Map<KeyValue, KeyboardData.PreferredPos> dst, Query q)
&& (alternatives.size() == 0 || !q.present.containsAll(alternatives)))
{
KeyValue kv_ = use_alternative ? alternatives.get(0) : kv;
dst.put(kv_, KeyboardData.PreferredPos.DEFAULT);
KeyboardData.PreferredPos pos = KeyboardData.PreferredPos.DEFAULT;
if (next_to != null)
{
pos = new KeyboardData.PreferredPos(pos);
pos.next_to = next_to;
}
dst.put(kv_, pos);
}
}

Expand All @@ -95,23 +104,33 @@ public void compute(Map<KeyValue, KeyboardData.PreferredPos> dst, Query q)
*/
public ExtraKey merge_with(ExtraKey k2)
{
String script_ =
(script != null && k2.script != null && script.equals(k2.script))
? script : null;
String script_ = one_or_none(script, k2.script);
List<KeyValue> alts = new ArrayList<KeyValue>(alternatives);
KeyValue next_to_ = one_or_none(next_to, k2.next_to);
alts.addAll(k2.alternatives);
return new ExtraKey(kv, script_, alts);
return new ExtraKey(kv, script_, alts, next_to_);
}

/** Extra keys are of the form "key name" or "key name:alt 1:alt 2". */
/** If one of [a] or [b] is null, return the other. If [a] and [b] are
equal, return [a]. Otherwise, return null. */
<E> E one_or_none(E a, E b)
{
return (a == null) ? b : (b == null || a.equals(b)) ? a : null;
}

/** Extra keys are of the form "key name" or "key name:alt1:alt2@next_to". */
public static ExtraKey parse(String str, String script)
{
String[] strs = str.split(":");
KeyValue kv = KeyValue.getKeyByName(strs[0]);
KeyValue[] alts = new KeyValue[strs.length-1];
for (int i = 1; i < strs.length; i++)
alts[i-1] = KeyValue.getKeyByName(strs[i]);
return new ExtraKey(kv, script, Arrays.asList(alts));
String[] split_on_at = str.split("@", 2);
String[] key_names = split_on_at[0].split(":");
KeyValue kv = KeyValue.getKeyByName(key_names[0]);
KeyValue[] alts = new KeyValue[key_names.length-1];
for (int i = 1; i < key_names.length; i++)
alts[i-1] = KeyValue.getKeyByName(key_names[i]);
KeyValue next_to = null;
if (split_on_at.length > 1)
next_to = KeyValue.getKeyByName(split_on_at[1]);
return new ExtraKey(kv, script, Arrays.asList(alts), next_to);
}
}

Expand Down
22 changes: 22 additions & 0 deletions srcs/juloo.keyboard2/KeyboardData.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ public KeyboardData addExtraKeys(Iterator<Map.Entry<KeyValue, PreferredPos>> ext
[rows]. Returns [false] if it couldn't be placed. */
boolean add_key_to_preferred_pos(List<Row> rows, KeyValue kv, PreferredPos pos)
{
if (pos.next_to != null)
{
KeyPos next_to_pos = getKeys().get(pos.next_to);
if (next_to_pos != null
&& add_key_to_pos(rows, kv, next_to_pos.with_dir(-1)))
return true;
}
for (KeyPos p : pos.positions)
if (add_key_to_pos(rows, kv, p))
return true;
Expand Down Expand Up @@ -521,6 +528,11 @@ public KeyPos(int r, int c, int d)
col = c;
dir = d;
}

public KeyPos with_dir(int d)
{
return new KeyPos(row, col, d);
}
}

/** See [addExtraKeys()]. */
Expand All @@ -529,6 +541,10 @@ public final static class PreferredPos
public static final PreferredPos DEFAULT;
public static final PreferredPos ANYWHERE;

/** Prefer the free position on the same keyboard key as the specified key.
Considered before [positions]. Might be [null]. */
public KeyValue next_to = null;

/** Array of positions to try in order. The special value [-1] as [row],
[col] or [dir] means that the field is unspecified. Every possible
values are tried for unspecified fields. Unspecified fields are
Expand All @@ -537,6 +553,12 @@ public final static class PreferredPos

public PreferredPos() {}

public PreferredPos(PreferredPos src)
{
next_to = src.next_to;
positions = src.positions;
}

static final KeyPos[] ANYWHERE_POSITIONS =
new KeyPos[]{ new KeyPos(-1, -1, -1) };

Expand Down

0 comments on commit d5cbcb3

Please sign in to comment.