abouttreesummaryrefslogcommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md9
-rw-r--r--srcs/juloo.keyboard2/Config.java28
-rw-r--r--srcs/juloo.keyboard2/Keyboard2.java2
-rw-r--r--srcs/juloo.keyboard2/KeyboardData.java95
4 files changed, 104 insertions, 30 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4a107b1..8a31530 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -83,17 +83,16 @@ make installd
A programming layout must contains every ASCII characters.
The current programming layouts are: QWERTY, Dvorak.
-Ideally, programming layouts should allow to type every Latin-script languages
-by containing every dead-keys. See for example: 0bf7ff5 (Latvian), 573c13f (Swedish).
-It is also possible to add some characters that are hidden in other languages,
-for example 93e84ba (ß), though the space is limited.
-
Layouts are defined in XML, see `res/xml/qwerty.xml`. An entry must be added to
the layout option in `res/values/arrays.xml`, to both `pref_layout_values`
(correspond to the file name) and `pref_layout_entries` (display name).
The layout must also be referenced in `srcs/juloo.keyboard2/Config.java` in
`layoutId_of_string`.
+Keys with a name starting in `loc ` are hidden unless they are configured for
+the user's installed languages in `res/xml/method.xml`. These keys are optional
+and will be added automatically when necessary.
+
Some users cannot easily type the characters close the the edges of the screen
due to a bulky phone case. It is best to avoid placing important characters
there (such as the digits or punctuation).
diff --git a/srcs/juloo.keyboard2/Config.java b/srcs/juloo.keyboard2/Config.java
index fd0c3ec..199fe35 100644
--- a/srcs/juloo.keyboard2/Config.java
+++ b/srcs/juloo.keyboard2/Config.java
@@ -9,6 +9,7 @@ import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.KeyEvent;
+import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;
@@ -142,20 +143,26 @@ final class Config
/** Update the layout according to the configuration.
* - Remove the switching key if it isn't needed
- * - Remove keys from other locales (not in 'extra_keys')
+ * - Remove "localized" keys from other locales (not in 'extra_keys')
* - Replace the action key to show the right label
* - Swap the enter and action keys
*/
- public KeyboardData modify_layout(KeyboardData kw)
+ public KeyboardData modify_layout(KeyboardData original_kw)
{
// Update the name to avoid caching in KeyModifier
final KeyValue action_key = (actionLabel == null) ? null :
KeyValue.getKeyByName("action").withNameAndSymbol(actionLabel, actionLabel);
- return kw.replaceKeys(new KeyboardData.MapKeys() {
+ // 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);
+ 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);
+ if (is_extra_key)
+ extra_keys.remove(key.name);
switch (key.eventCode)
{
case KeyValue.EVENT_CHANGE_METHOD:
@@ -170,9 +177,7 @@ final class Config
default:
if (key.flags != 0)
{
- if ((key.flags & KeyValue.FLAG_LOCALIZED) != 0 &&
- extra_keys != null &&
- !extra_keys.contains(key.name))
+ if ((key.flags & KeyValue.FLAG_LOCALIZED) != 0 && !is_extra_key)
return null;
if ((key.flags & lockable_modifiers) != 0)
return key.withFlags(key.flags | KeyValue.FLAG_LOCK);
@@ -181,6 +186,17 @@ 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()); }
+ });
+ }
+ return kw;
}
private float getDipPref(DisplayMetrics dm, SharedPreferences prefs, String pref_name, float def)
diff --git a/srcs/juloo.keyboard2/Keyboard2.java b/srcs/juloo.keyboard2/Keyboard2.java
index d9f0012..8ebf0b8 100644
--- a/srcs/juloo.keyboard2/Keyboard2.java
+++ b/srcs/juloo.keyboard2/Keyboard2.java
@@ -295,7 +295,7 @@ public class Keyboard2 extends InputMethodService
if (_config.programming_layout == -1)
return;
KeyboardData layout =
- getLayout(_config.programming_layout).replaceKeys(new KeyboardData.MapKeys() {
+ getLayout(_config.programming_layout).mapKeys(new KeyboardData.MapKeyValues() {
public KeyValue apply(KeyValue key)
{
if (key != null && key.eventCode == KeyValue.EVENT_SWITCH_PROGRAMMING)
diff --git a/srcs/juloo.keyboard2/KeyboardData.java b/srcs/juloo.keyboard2/KeyboardData.java
index adbf790..83b1548 100644
--- a/srcs/juloo.keyboard2/KeyboardData.java
+++ b/srcs/juloo.keyboard2/KeyboardData.java
@@ -3,10 +3,11 @@ package juloo.keyboard2;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import java.util.ArrayList;
+import java.util.function.Function;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.function.Function;
class KeyboardData
{
@@ -16,14 +17,42 @@ class KeyboardData
/* Total height of the keyboard. Unit is abstract. */
public final float keysHeight;
- public KeyboardData replaceKeys(MapKeys f)
+ public KeyboardData mapKeys(MapKey f)
{
ArrayList<Row> rows_ = new ArrayList<Row>();
for (Row r : rows)
- rows_.add(r.replaceKeys(f));
+ rows_.add(r.mapKeys(f));
return new KeyboardData(rows_, keysWidth);
}
+ /** Add keys from the given iterator into the keyboard. Extra keys are added
+ * on the empty key4 corner of the second row, from right to left. If there's
+ * not enough room, key3 of the second row is tried then key2 and key1 of the
+ * third row. */
+ public KeyboardData addExtraKeys(Iterator<KeyValue> k)
+ {
+ ArrayList<Row> rows = new ArrayList<Row>(this.rows);
+ addExtraKeys_to_row(rows, k, 1, 4);
+ addExtraKeys_to_row(rows, k, 1, 3);
+ addExtraKeys_to_row(rows, k, 2, 2);
+ addExtraKeys_to_row(rows, k, 2, 1);
+ return new KeyboardData(rows, keysWidth);
+ }
+
+ private static void addExtraKeys_to_row(ArrayList<Row> rows, final Iterator<KeyValue> extra_keys, int row_i, final int d)
+ {
+ if (!extra_keys.hasNext())
+ return;
+ rows.set(row_i, rows.get(row_i).mapKeys(new MapKey(){
+ public Key apply(Key k) {
+ if (k.getKeyValue(d) == null && extra_keys.hasNext())
+ return k.withKeyValue(d, extra_keys.next());
+ else
+ return k;
+ }
+ }));
+ }
+
private static Row _bottomRow = null;
private static Map<Integer, KeyboardData> _layoutCache = new HashMap<Integer, KeyboardData>();
@@ -117,22 +146,21 @@ class KeyboardData
return new Row(keys, h, shift);
}
- public Row replaceKeys(MapKeys f)
+ public Row mapKeys(MapKey f)
{
ArrayList<Key> keys_ = new ArrayList<Key>();
for (Key k : keys)
- keys_.add(k.replaceKeys(f));
+ keys_.add(f.apply(k));
return new Row(keys_, height, shift);
}
/** Change the width of every keys so that the row is 's' units wide. */
public Row updateWidth(float newWidth)
{
- float s = newWidth / keysWidth;
- ArrayList<Key> keys_ = new ArrayList<Key>();
- for (Key k : keys)
- keys_.add(k.scaleWidth(s));
- return new Row(keys_, height, shift);
+ final float s = newWidth / keysWidth;
+ return mapKeys(new MapKey(){
+ public Key apply(Key k) { return k.scaleWidth(s); }
+ });
}
}
@@ -183,18 +211,39 @@ class KeyboardData
return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys);
}
- public Key replaceKeys(MapKeys f)
- {
- return new Key(f.apply(key0), f.apply(key1), f.apply(key2),
- f.apply(key3), f.apply(key4), width, shift, edgekeys);
- }
-
/** New key with the width multiplied by 's'. */
public Key scaleWidth(float s)
{
return new Key(key0, key1, key2, key3, key4, width * s, shift, edgekeys);
}
+ public KeyValue getKeyValue(int i)
+ {
+ switch (i)
+ {
+ case 0: return key0;
+ case 1: return key1;
+ case 2: return key2;
+ case 3: return key3;
+ case 4: return key4;
+ default: return null;
+ }
+ }
+
+ public Key withKeyValue(int i, KeyValue kv)
+ {
+ KeyValue k0 = key0, k1 = key1, k2 = key2, k3 = key3, k4 = key4;
+ switch (i)
+ {
+ case 0: k0 = kv; break;
+ case 1: k1 = kv; break;
+ case 2: k2 = kv; break;
+ case 3: k3 = kv; break;
+ case 4: k4 = kv; break;
+ }
+ return new Key(k0, k1, k2, k3, k4, width, shift, edgekeys);
+ }
+
/*
* See Pointers.onTouchMove() for the represented direction.
*/
@@ -235,8 +284,18 @@ class KeyboardData
}
// Not using Function<KeyValue, KeyValue> to keep compatibility with Android 6.
- public static abstract interface MapKeys {
- public KeyValue apply(KeyValue kv);
+ public static abstract interface MapKey {
+ public Key apply(Key k);
+ }
+
+ public static abstract class MapKeyValues implements MapKey {
+ abstract public KeyValue apply(KeyValue kv);
+
+ public Key apply(Key k)
+ {
+ return new Key(apply(k.key0), apply(k.key1), apply(k.key2),
+ apply(k.key3), apply(k.key4), k.width, k.shift, k.edgekeys);
+ }
}
/** Parsing utils */