diff options
Diffstat (limited to 'srcs/juloo.keyboard2/LayoutsPreference.java')
| -rw-r--r-- | srcs/juloo.keyboard2/LayoutsPreference.java | 173 |
1 files changed, 157 insertions, 16 deletions
diff --git a/srcs/juloo.keyboard2/LayoutsPreference.java b/srcs/juloo.keyboard2/LayoutsPreference.java index ba28630..a65b350 100644 --- a/srcs/juloo.keyboard2/LayoutsPreference.java +++ b/srcs/juloo.keyboard2/LayoutsPreference.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.res.Resources; +import android.content.res.TypedArray; import android.util.AttributeSet; import android.widget.ArrayAdapter; import android.widget.EditText; @@ -12,16 +13,17 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import org.json.JSONException; +import org.json.JSONObject; -public class LayoutsPreference extends ListGroupPreference<String> +public class LayoutsPreference extends ListGroupPreference<LayoutsPreference.Layout> { static final String KEY = "layouts"; - static final List<String> DEFAULT = Collections.singletonList("system"); - static final ListGroupPreference.Serializer<String> SERIALIZER = - new ListGroupPreference.StringSerializer(); + static final List<Layout> DEFAULT = + Collections.singletonList((Layout)new SystemLayout()); + static final ListGroupPreference.Serializer<Layout> SERIALIZER = + new Serializer(); - /** Layout names as stored in the preferences. */ - List<String> _layout_names; /** Text displayed for each layout in the dialog list. */ String[] _layout_display_names; @@ -30,13 +32,56 @@ public class LayoutsPreference extends ListGroupPreference<String> super(ctx, attrs); setKey(KEY); Resources res = ctx.getResources(); - _layout_names = Arrays.asList(res.getStringArray(R.array.pref_layout_values)); _layout_display_names = res.getStringArray(R.array.pref_layout_entries); } - public static List<String> load_from_preferences(SharedPreferences prefs) + /** Obtained from [res/values/layouts.xml]. */ + static List<String> _unsafe_layout_ids_str = null; + static TypedArray _unsafe_layout_ids_res = null; + + /** Layout internal names. Contains "system" and "custom". */ + public static List<String> get_layout_names(Resources res) + { + if (_unsafe_layout_ids_str == null) + _unsafe_layout_ids_str = Arrays.asList( + res.getStringArray(R.array.pref_layout_values)); + return _unsafe_layout_ids_str; + } + + /** Layout resource id for a layout name. [-1] if not found. */ + public static int layout_id_of_name(Resources res, String name) + { + if (_unsafe_layout_ids_res == null) + _unsafe_layout_ids_res = res.obtainTypedArray(R.array.layout_ids); + int i = get_layout_names(res).indexOf(name); + if (i >= 0) + return _unsafe_layout_ids_res.getResourceId(i, 0); + return -1; + } + + /** [null] for the "system" layout. */ + public static List<KeyboardData> load_from_preferences(Resources res, SharedPreferences prefs) + { + List<KeyboardData> layouts = new ArrayList<KeyboardData>(); + for (Layout l : load_from_preferences(KEY, prefs, DEFAULT, SERIALIZER)) + { + if (l instanceof NamedLayout) + layouts.add(layout_of_string(res, ((NamedLayout)l).name)); + else if (l instanceof CustomLayout) + layouts.add(KeyboardData.load_string(((CustomLayout)l).xml)); + else // instanceof SystemLayout + layouts.add(null); + } + return layouts; + } + + public static KeyboardData layout_of_string(Resources res, String name) { - return load_from_preferences(KEY, prefs, DEFAULT, SERIALIZER); + int id = layout_id_of_name(res, name); + if (id > 0) + return KeyboardData.load(res, id); + // Might happen when the app is downgraded, return the system layout. + return null; } @Override @@ -44,15 +89,28 @@ public class LayoutsPreference extends ListGroupPreference<String> { super.onSetInitialValue(restoreValue, defaultValue); if (_values.size() == 0) - set_values(new ArrayList<String>(DEFAULT), false); + set_values(new ArrayList<Layout>(DEFAULT), false); + } + + String label_of_layout(Layout l) + { + if (l instanceof NamedLayout) + { + String lname = ((NamedLayout)l).name; + int value_i = get_layout_names(getContext().getResources()).indexOf(lname); + return value_i < 0 ? lname : _layout_display_names[value_i]; + } + else if (l instanceof CustomLayout) + return getContext().getString(R.string.pref_layout_e_custom); + else // instanceof SystemLayout + return getContext().getString(R.string.pref_layout_e_system); } @Override - String label_of_value(String value, int i) + String label_of_value(Layout value, int i) { - int value_i = _layout_names.indexOf(value); - String lname = value_i < 0 ? value : _layout_display_names[value_i]; - return getContext().getString(R.string.pref_layouts_item, i + 1, lname); + return getContext().getString(R.string.pref_layouts_item, i + 1, + label_of_layout(value)); } @Override @@ -70,7 +128,7 @@ public class LayoutsPreference extends ListGroupPreference<String> } @Override - Serializer<String> get_serializer() { return SERIALIZER; } + ListGroupPreference.Serializer<Layout> get_serializer() { return SERIALIZER; } @Override void select(final SelectionCallback callback) @@ -81,9 +139,37 @@ public class LayoutsPreference extends ListGroupPreference<String> .setAdapter(layouts, new DialogInterface.OnClickListener(){ public void onClick(DialogInterface _dialog, int which) { - callback.select(_layout_names.get(which)); + String name = get_layout_names(getContext().getResources()).get(which); + switch (name) + { + case "system": + callback.select(new SystemLayout()); + break; + case "custom": + select_custom(callback); + break; + default: + callback.select(new NamedLayout(name)); + break; + } + } + }) + .show(); + } + + void select_custom(final SelectionCallback callback) + { + new AlertDialog.Builder(getContext()) + .setView(R.layout.dialog_edit_text) + .setTitle(R.string.pref_custom_layout_title) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener(){ + public void onClick(DialogInterface dialog, int _which) + { + EditText input = (EditText)((AlertDialog)dialog).findViewById(R.id.text); + callback.select(new CustomLayout(input.getText().toString())); } }) + .setNegativeButton(android.R.string.cancel, null) .show(); } @@ -95,4 +181,59 @@ public class LayoutsPreference extends ListGroupPreference<String> setLayoutResource(R.layout.pref_layouts_add_btn); } } + + /** A layout selected by the user. The only implementations are + [NamedLayout], [SystemLayout] and [CustomLayout]. */ + interface Layout {} + + static final class SystemLayout implements Layout + { + public SystemLayout() {} + } + + /** The name of a layout defined in [res/xml]. */ + static final class NamedLayout implements Layout + { + public final String name; + public NamedLayout(String n) { name = n; } + } + + /** The XML description of a custom layout. */ + static final class CustomLayout implements Layout + { + public final String xml; + public CustomLayout(String c) { xml = c; } + } + + /** Named layouts are serialized to strings and custom layouts to JSON + objects with a [kind] field. */ + static class Serializer implements ListGroupPreference.Serializer<Layout> + { + public Layout load_item(Object obj) throws JSONException + { + if (obj instanceof String) + { + String name = (String)obj; + if (name.equals("system")) + return new SystemLayout(); + return new NamedLayout(name); + } + JSONObject obj_ = (JSONObject)obj; + switch (obj_.getString("kind")) + { + case "custom": return new CustomLayout(obj_.getString("xml")); + case "system": default: return new SystemLayout(); + } + } + + public Object save_item(Layout v) throws JSONException + { + if (v instanceof NamedLayout) + return ((NamedLayout)v).name; + if (v instanceof CustomLayout) + return new JSONObject().put("kind", "custom") + .put("xml", ((CustomLayout)v).xml); + return new JSONObject().put("kind", "system"); + } + } } |
