mirror of
https://github.com/Julow/Unexpected-Keyboard.git
synced 2025-08-14 12:18:52 +02:00
413 lines
12 KiB
Java
413 lines
12 KiB
Java
package juloo.keyboard2.prefs;
|
|
|
|
import android.content.Context;
|
|
import android.content.SharedPreferences;
|
|
import android.content.res.Resources;
|
|
import android.os.Build.VERSION;
|
|
import android.preference.CheckBoxPreference;
|
|
import android.preference.PreferenceCategory;
|
|
import android.util.AttributeSet;
|
|
import android.view.View;
|
|
import android.widget.TextView;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import juloo.keyboard2.*;
|
|
|
|
/** This class implements the "extra keys" preference but also defines the
|
|
possible extra keys. */
|
|
public class ExtraKeysPreference extends PreferenceCategory
|
|
{
|
|
/** Array of the keys that can be selected. */
|
|
public static String[] extra_keys = new String[]
|
|
{
|
|
"alt",
|
|
"meta",
|
|
"compose",
|
|
"voice_typing",
|
|
"switch_clipboard",
|
|
"accent_aigu",
|
|
"accent_grave",
|
|
"accent_double_aigu",
|
|
"accent_dot_above",
|
|
"accent_circonflexe",
|
|
"accent_tilde",
|
|
"accent_cedille",
|
|
"accent_trema",
|
|
"accent_ring",
|
|
"accent_caron",
|
|
"accent_macron",
|
|
"accent_ogonek",
|
|
"accent_breve",
|
|
"accent_slash",
|
|
"accent_bar",
|
|
"accent_dot_below",
|
|
"accent_hook_above",
|
|
"accent_horn",
|
|
"accent_double_grave",
|
|
"€",
|
|
"ß",
|
|
"£",
|
|
"§",
|
|
"†",
|
|
"ª",
|
|
"º",
|
|
"zwj",
|
|
"zwnj",
|
|
"nbsp",
|
|
"nnbsp",
|
|
"tab",
|
|
"esc",
|
|
"page_up",
|
|
"page_down",
|
|
"home",
|
|
"end",
|
|
"switch_greekmath",
|
|
"change_method",
|
|
"capslock",
|
|
"copy",
|
|
"paste",
|
|
"cut",
|
|
"selectAll",
|
|
"shareText",
|
|
"pasteAsPlainText",
|
|
"undo",
|
|
"redo",
|
|
"delete_word",
|
|
"forward_delete_word",
|
|
"superscript",
|
|
"subscript",
|
|
"f11_placeholder",
|
|
"f12_placeholder",
|
|
"menu",
|
|
"scroll_lock",
|
|
"combining_dot_above",
|
|
"combining_double_aigu",
|
|
"combining_slash",
|
|
"combining_arrow_right",
|
|
"combining_breve",
|
|
"combining_bar",
|
|
"combining_aigu",
|
|
"combining_caron",
|
|
"combining_cedille",
|
|
"combining_circonflexe",
|
|
"combining_grave",
|
|
"combining_macron",
|
|
"combining_ring",
|
|
"combining_tilde",
|
|
"combining_trema",
|
|
"combining_ogonek",
|
|
"combining_dot_below",
|
|
"combining_horn",
|
|
"combining_hook_above",
|
|
"combining_vertical_tilde",
|
|
"combining_inverted_breve",
|
|
"combining_pokrytie",
|
|
"combining_slavonic_psili",
|
|
"combining_slavonic_dasia",
|
|
"combining_payerok",
|
|
"combining_titlo",
|
|
"combining_vzmet",
|
|
"combining_arabic_v",
|
|
"combining_arabic_inverted_v",
|
|
"combining_shaddah",
|
|
"combining_sukun",
|
|
"combining_fatha",
|
|
"combining_dammah",
|
|
"combining_kasra",
|
|
"combining_hamza_above",
|
|
"combining_hamza_below",
|
|
"combining_alef_above",
|
|
"combining_fathatan",
|
|
"combining_kasratan",
|
|
"combining_dammatan",
|
|
"combining_alef_below",
|
|
"combining_kavyka",
|
|
"combining_palatalization",
|
|
};
|
|
|
|
/** Whether an extra key is enabled by default. */
|
|
public static boolean default_checked(String name)
|
|
{
|
|
switch (name)
|
|
{
|
|
case "voice_typing":
|
|
case "change_method":
|
|
case "switch_clipboard":
|
|
case "compose":
|
|
case "tab":
|
|
case "esc":
|
|
case "f11_placeholder":
|
|
case "f12_placeholder":
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/** Text that describe a key. Might be null. */
|
|
static String key_description(Resources res, String name)
|
|
{
|
|
int id = 0;
|
|
String additional_info = null;
|
|
switch (name)
|
|
{
|
|
case "capslock": id = R.string.key_descr_capslock; break;
|
|
case "change_method": id = R.string.key_descr_change_method; break;
|
|
case "compose": id = R.string.key_descr_compose; break;
|
|
case "copy": id = R.string.key_descr_copy; break;
|
|
case "cut": id = R.string.key_descr_cut; break;
|
|
case "end":
|
|
id = R.string.key_descr_end;
|
|
additional_info = format_key_combination(new String[]{"fn", "right"});
|
|
break;
|
|
case "home":
|
|
id = R.string.key_descr_home;
|
|
additional_info = format_key_combination(new String[]{"fn", "left"});
|
|
break;
|
|
case "page_down":
|
|
id = R.string.key_descr_page_down;
|
|
additional_info = format_key_combination(new String[]{"fn", "down"});
|
|
break;
|
|
case "page_up":
|
|
id = R.string.key_descr_page_up;
|
|
additional_info = format_key_combination(new String[]{"fn", "up"});
|
|
break;
|
|
case "paste": id = R.string.key_descr_paste; break;
|
|
case "pasteAsPlainText":
|
|
id = R.string.key_descr_pasteAsPlainText;
|
|
additional_info = format_key_combination(new String[]{"fn", "paste"});
|
|
break;
|
|
case "redo":
|
|
id = R.string.key_descr_redo;
|
|
additional_info = format_key_combination(new String[]{"fn", "undo"});
|
|
break;
|
|
case "delete_word":
|
|
id = R.string.key_descr_delete_word;
|
|
additional_info = format_key_combination_gesture(res, "backspace");
|
|
break;
|
|
case "forward_delete_word":
|
|
id = R.string.key_descr_forward_delete_word;
|
|
additional_info = format_key_combination_gesture(res, "forward_delete");
|
|
break;
|
|
case "selectAll": id = R.string.key_descr_selectAll; break;
|
|
case "subscript": id = R.string.key_descr_subscript; break;
|
|
case "superscript": id = R.string.key_descr_superscript; break;
|
|
case "switch_greekmath": id = R.string.key_descr_switch_greekmath; break;
|
|
case "undo": id = R.string.key_descr_undo; break;
|
|
case "voice_typing": id = R.string.key_descr_voice_typing; break;
|
|
case "ª": id = R.string.key_descr_ª; break;
|
|
case "º": id = R.string.key_descr_º; break;
|
|
case "switch_clipboard": id = R.string.key_descr_clipboard; break;
|
|
case "zwj": id = R.string.key_descr_zwj; break;
|
|
case "zwnj": id = R.string.key_descr_zwnj; break;
|
|
case "nbsp": id = R.string.key_descr_nbsp; break;
|
|
case "nnbsp": id = R.string.key_descr_nnbsp; break;
|
|
|
|
case "accent_aigu":
|
|
case "accent_grave":
|
|
case "accent_double_aigu":
|
|
case "accent_dot_above":
|
|
case "accent_circonflexe":
|
|
case "accent_tilde":
|
|
case "accent_cedille":
|
|
case "accent_trema":
|
|
case "accent_ring":
|
|
case "accent_caron":
|
|
case "accent_macron":
|
|
case "accent_ogonek":
|
|
case "accent_breve":
|
|
case "accent_slash":
|
|
case "accent_bar":
|
|
case "accent_dot_below":
|
|
case "accent_hook_above":
|
|
case "accent_horn":
|
|
case "accent_double_grave":
|
|
id = R.string.key_descr_dead_key;
|
|
break;
|
|
|
|
case "combining_dot_above":
|
|
case "combining_double_aigu":
|
|
case "combining_slash":
|
|
case "combining_arrow_right":
|
|
case "combining_breve":
|
|
case "combining_bar":
|
|
case "combining_aigu":
|
|
case "combining_caron":
|
|
case "combining_cedille":
|
|
case "combining_circonflexe":
|
|
case "combining_grave":
|
|
case "combining_macron":
|
|
case "combining_ring":
|
|
case "combining_tilde":
|
|
case "combining_trema":
|
|
case "combining_ogonek":
|
|
case "combining_dot_below":
|
|
case "combining_horn":
|
|
case "combining_hook_above":
|
|
case "combining_vertical_tilde":
|
|
case "combining_inverted_breve":
|
|
case "combining_pokrytie":
|
|
case "combining_slavonic_psili":
|
|
case "combining_slavonic_dasia":
|
|
case "combining_payerok":
|
|
case "combining_titlo":
|
|
case "combining_vzmet":
|
|
case "combining_arabic_v":
|
|
case "combining_arabic_inverted_v":
|
|
case "combining_shaddah":
|
|
case "combining_sukun":
|
|
case "combining_fatha":
|
|
case "combining_dammah":
|
|
case "combining_kasra":
|
|
case "combining_hamza_above":
|
|
case "combining_hamza_below":
|
|
case "combining_alef_above":
|
|
case "combining_fathatan":
|
|
case "combining_kasratan":
|
|
case "combining_dammatan":
|
|
case "combining_alef_below":
|
|
case "combining_kavyka":
|
|
case "combining_palatalization":
|
|
id = R.string.key_descr_combining;
|
|
break;
|
|
}
|
|
if (id == 0)
|
|
return additional_info;
|
|
String descr = res.getString(id);
|
|
if (additional_info != null)
|
|
descr += " — " + additional_info;
|
|
return descr;
|
|
}
|
|
|
|
static String key_title(String key_name, KeyValue kv)
|
|
{
|
|
switch (key_name)
|
|
{
|
|
case "f11_placeholder": return "F11";
|
|
case "f12_placeholder": return "F12";
|
|
}
|
|
return kv.getString();
|
|
}
|
|
|
|
/** Format a key combination */
|
|
static String format_key_combination(String[] keys)
|
|
{
|
|
StringBuilder out = new StringBuilder();
|
|
for (int i = 0; i < keys.length; i++)
|
|
{
|
|
if (i > 0) out.append(" + ");
|
|
out.append(KeyValue.getKeyByName(keys[i]).getString());
|
|
}
|
|
return out.toString();
|
|
}
|
|
|
|
/** Explain a gesture on a key */
|
|
static String format_key_combination_gesture(Resources res, String key_name)
|
|
{
|
|
return res.getString(R.string.key_descr_gesture) + " + "
|
|
+ KeyValue.getKeyByName(key_name).getString();
|
|
}
|
|
|
|
/** Place an extra key next to the key specified by the first argument, on
|
|
bottom-right preferably or on the bottom-left. If the specified key is not
|
|
on the layout, place on the specified row and column. */
|
|
static KeyboardData.PreferredPos mk_preferred_pos(String next_to_key, int row, int col, boolean prefer_bottom_right)
|
|
{
|
|
KeyValue next_to = (next_to_key == null) ? null : KeyValue.getKeyByName(next_to_key);
|
|
int d1, d2; // Preferred direction and fallback direction
|
|
if (prefer_bottom_right) { d1 = 4; d2 = 3; } else { d1 = 3; d2 = 4; }
|
|
return new KeyboardData.PreferredPos(next_to,
|
|
new KeyboardData.KeyPos[]{
|
|
new KeyboardData.KeyPos(row, col, d1),
|
|
new KeyboardData.KeyPos(row, col, d2),
|
|
new KeyboardData.KeyPos(row, -1, d1),
|
|
new KeyboardData.KeyPos(row, -1, d2),
|
|
new KeyboardData.KeyPos(-1, -1, -1),
|
|
});
|
|
}
|
|
|
|
static KeyboardData.PreferredPos key_preferred_pos(String key_name)
|
|
{
|
|
switch (key_name)
|
|
{
|
|
case "cut": return mk_preferred_pos("x", 2, 2, true);
|
|
case "copy": return mk_preferred_pos("c", 2, 3, true);
|
|
case "paste": return mk_preferred_pos("v", 2, 4, true);
|
|
case "undo": return mk_preferred_pos("z", 2, 1, true);
|
|
case "selectAll": return mk_preferred_pos("a", 1, 0, true);
|
|
case "redo": return mk_preferred_pos("y", 0, 5, true);
|
|
case "f11_placeholder": return mk_preferred_pos("9", 0, 8, false);
|
|
case "f12_placeholder": return mk_preferred_pos("0", 0, 9, false);
|
|
case "delete_word": return mk_preferred_pos("backspace", -1, -1, false);
|
|
case "forward_delete_word": return mk_preferred_pos("backspace", -1, -1, true);
|
|
}
|
|
return KeyboardData.PreferredPos.DEFAULT;
|
|
}
|
|
|
|
/** Get the set of enabled extra keys. */
|
|
public static Map<KeyValue, KeyboardData.PreferredPos> get_extra_keys(SharedPreferences prefs)
|
|
{
|
|
Map<KeyValue, KeyboardData.PreferredPos> ks =
|
|
new HashMap<KeyValue, KeyboardData.PreferredPos>();
|
|
for (String key_name : extra_keys)
|
|
{
|
|
if (prefs.getBoolean(pref_key_of_key_name(key_name),
|
|
default_checked(key_name)))
|
|
ks.put(KeyValue.getKeyByName(key_name), key_preferred_pos(key_name));
|
|
}
|
|
return ks;
|
|
}
|
|
|
|
boolean _attached = false; /** Whether it has already been attached. */
|
|
|
|
public ExtraKeysPreference(Context context, AttributeSet attrs)
|
|
{
|
|
super(context, attrs);
|
|
setOrderingAsAdded(true);
|
|
}
|
|
|
|
@Override
|
|
protected void onAttachedToActivity()
|
|
{
|
|
if (_attached)
|
|
return;
|
|
_attached = true;
|
|
for (String key_name : extra_keys)
|
|
addPreference(new ExtraKeyCheckBoxPreference(getContext(), key_name,
|
|
default_checked(key_name)));
|
|
}
|
|
|
|
public static String pref_key_of_key_name(String key_name)
|
|
{
|
|
return "extra_key_" + key_name;
|
|
}
|
|
|
|
static class ExtraKeyCheckBoxPreference extends CheckBoxPreference
|
|
{
|
|
public ExtraKeyCheckBoxPreference(Context ctx, String key_name,
|
|
boolean default_checked)
|
|
{
|
|
super(ctx);
|
|
KeyValue kv = KeyValue.getKeyByName(key_name);
|
|
String title = key_title(key_name, kv);
|
|
String descr = key_description(ctx.getResources(), key_name);
|
|
if (descr != null)
|
|
title += " (" + descr + ")";
|
|
setKey(pref_key_of_key_name(key_name));
|
|
setDefaultValue(default_checked);
|
|
setTitle(title);
|
|
if (VERSION.SDK_INT >= 26)
|
|
setSingleLineTitle(false);
|
|
}
|
|
|
|
@Override
|
|
protected void onBindView(View view)
|
|
{
|
|
super.onBindView(view);
|
|
TextView title = (TextView)view.findViewById(android.R.id.title);
|
|
title.setTypeface(Theme.getKeyFont(getContext()));
|
|
}
|
|
}
|
|
}
|