Add custom subtype settings
Bug: 4460018 Change-Id: I4919d79516dcf574be2761bbaf9adcdc381b2ddcmain
parent
344af15674
commit
c27fe6253c
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2012, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:columnCount="2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="8dip"
|
||||
android:layout_marginRight="8dip"
|
||||
android:padding="8dip">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left|center_vertical"
|
||||
style="?android:attr/textAppearanceSmall"
|
||||
android:text="@string/subtype_locale" />
|
||||
<Spinner
|
||||
android:id="@+id/subtype_locale_spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginLeft="8dip"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:layout_marginTop="8dip"
|
||||
android:layout_gravity="fill_horizontal|center_vertical"
|
||||
android:prompt="@string/subtype_locale" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left|center_vertical"
|
||||
style="?android:attr/textAppearanceSmall"
|
||||
android:text="@string/keyboard_layout_set" />
|
||||
<Spinner
|
||||
android:id="@+id/keyboard_layout_set_spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginLeft="8dip"
|
||||
android:layout_marginBottom="8dip"
|
||||
android:layout_marginTop="8dip"
|
||||
android:layout_gravity="fill_horizontal|center_vertical"
|
||||
android:prompt="@string/keyboard_layout_set" />
|
||||
</GridLayout>
|
|
@ -252,9 +252,26 @@
|
|||
<string name="subtype_en_GB">English (UK)</string>
|
||||
<!-- Description for English (United States) keyboard subtype [CHAR LIMIT=22] -->
|
||||
<string name="subtype_en_US">English (US)</string>
|
||||
<!-- Description for language agnostic keyboard subtype [CHAR LIMIT=22] -->
|
||||
<string name="subtype_no_language">No language</string>
|
||||
<!-- Description for language agnostic QWERTY keyboard subtype [CHAR LIMIT=22] -->
|
||||
<string name="subtype_no_language_qwerty">No language (QWERTY)</string>
|
||||
|
||||
<!-- Title of the preference settings for custom input styles (language and keyboard layout pairs) [CHAR LIMIT=22]-->
|
||||
<string name="custom_input_styles_title">Custom input styles</string>
|
||||
<!-- Title of the option menu to add a new style entry in the preference settings [CHAR_LIMIT=12] -->
|
||||
<string name="add_style">Add style</string>
|
||||
<!-- Title of the button to add custom style entry in the settings dialog [CHAR_LIMIT=12] -->
|
||||
<string name="add">Add</string>
|
||||
<!-- Title of the button to remove a custom style entry in the settings dialog [CHAR_LIMIT=12] -->
|
||||
<string name="remove">Remove</string>
|
||||
<!-- Title of the button to save a custom style entry in the settings dialog [CHAR_LIMIT=12] -->
|
||||
<string name="save">Save</string>
|
||||
<!-- Title of the spinner for choosing a language of custom style in the settings dialog [CHAR_LIMIT=12] -->
|
||||
<string name="subtype_locale">Language</string>
|
||||
<!-- Title of the spinner for choosing a keyboard layout of custom style in the settings dialog [CHAR_LIMIT=12] -->
|
||||
<string name="keyboard_layout_set">Layout</string>
|
||||
|
||||
<!-- Title of an option for usability study mode -->
|
||||
<string name="prefs_usability_study_mode">Usability study mode</string>
|
||||
<!-- Title of the settings for keypress vibration duration -->
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2012 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Items will be added at runtime -->
|
||||
</PreferenceScreen>
|
|
@ -100,6 +100,10 @@
|
|||
android:summary="@string/include_other_imes_in_language_switch_list_summary"
|
||||
android:persistent="true"
|
||||
android:defaultValue="false" />
|
||||
<PreferenceScreen
|
||||
android:fragment="com.android.inputmethod.latin.AdditionalSubtypeSettings"
|
||||
android:key="custom_input_styles"
|
||||
android:title="@string/custom_input_styles_title" />
|
||||
<!-- Values for popup dismiss delay are added programatically -->
|
||||
<ListPreference
|
||||
android:key="pref_key_preview_popup_dismiss_delay"
|
||||
|
|
|
@ -24,6 +24,11 @@ public class AdditionalSubtype {
|
|||
public static final String QWERTY = "qwerty";
|
||||
public static final String QWERTZ = "qwertz";
|
||||
public static final String AZERTY = "azerty";
|
||||
public static final String[] PREDEFINED_KEYBOARD_LAYOUT_SET = {
|
||||
QWERTY,
|
||||
QWERTZ,
|
||||
AZERTY
|
||||
};
|
||||
|
||||
private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
|
||||
private static final String SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype";
|
||||
|
@ -38,40 +43,60 @@ public class AdditionalSubtype {
|
|||
sKeyboardLayoutToNameIdsMap.put(AZERTY, R.string.subtype_generic_azerty);
|
||||
}
|
||||
|
||||
private AdditionalSubtype() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
public static boolean isAdditionalSubtype(InputMethodSubtype subtype) {
|
||||
return subtype.containsExtraValueKey(SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE);
|
||||
}
|
||||
|
||||
private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":";
|
||||
public static final String PREF_SUBTYPE_SEPARATOR = ";";
|
||||
|
||||
public static InputMethodSubtype createAdditionalSubtype(
|
||||
String localeString, String keyboardLayoutSetName, String extraValue) {
|
||||
final String layoutExtraValue = LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET + "="
|
||||
+ keyboardLayoutSetName;
|
||||
final String filteredExtraValue = StringUtils.appendToCsvIfNotExists(
|
||||
SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE,
|
||||
StringUtils.removeFromCsvIfExists(layoutExtraValue, extraValue));
|
||||
SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE, extraValue);
|
||||
Integer nameId = sKeyboardLayoutToNameIdsMap.get(keyboardLayoutSetName);
|
||||
if (nameId == null) nameId = R.string.subtype_generic;
|
||||
return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard,
|
||||
localeString, SUBTYPE_MODE_KEYBOARD, filteredExtraValue, false, false);
|
||||
localeString, SUBTYPE_MODE_KEYBOARD,
|
||||
layoutExtraValue + "," + filteredExtraValue, false, false);
|
||||
}
|
||||
|
||||
private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":";
|
||||
private static final String PREF_SUBTYPE_SEPARATOR = ";";
|
||||
public static String getPrefSubtype(InputMethodSubtype subtype) {
|
||||
final String localeString = subtype.getLocale();
|
||||
final String keyboardLayoutSetName = SubtypeLocale.getKeyboardLayoutSetName(subtype);
|
||||
final String layoutExtraValue = LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET + "="
|
||||
+ keyboardLayoutSetName;
|
||||
final String extraValue = StringUtils.removeFromCsvIfExists(layoutExtraValue,
|
||||
StringUtils.removeFromCsvIfExists(SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE,
|
||||
subtype.getExtraValue()));
|
||||
final String basePrefSubtype = localeString + LOCALE_AND_LAYOUT_SEPARATOR
|
||||
+ keyboardLayoutSetName;
|
||||
return extraValue.isEmpty() ? basePrefSubtype
|
||||
: basePrefSubtype + LOCALE_AND_LAYOUT_SEPARATOR + extraValue;
|
||||
}
|
||||
|
||||
public static InputMethodSubtype createAdditionalSubtype(String prefSubtype) {
|
||||
final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR);
|
||||
if (elems.length < 2 || elems.length > 3) {
|
||||
throw new RuntimeException("Unknown additional subtype specified: " + prefSubtype);
|
||||
}
|
||||
final String localeString = elems[0];
|
||||
final String keyboardLayoutSetName = elems[1];
|
||||
final String extraValue = (elems.length == 3) ? elems[2] : null;
|
||||
return createAdditionalSubtype(localeString, keyboardLayoutSetName, extraValue);
|
||||
}
|
||||
|
||||
public static InputMethodSubtype[] createAdditionalSubtypesArray(String prefSubtypes) {
|
||||
final String[] prefSubtypeArray = prefSubtypes.split(PREF_SUBTYPE_SEPARATOR);
|
||||
final InputMethodSubtype[] subtypesArray = new InputMethodSubtype[prefSubtypeArray.length];
|
||||
for (int i = 0; i < prefSubtypeArray.length; i++) {
|
||||
final String prefSubtype = prefSubtypeArray[i];
|
||||
final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR);
|
||||
if (elems.length < 2 || elems.length > 3) {
|
||||
throw new RuntimeException("Unknown subtype found in preference: " + prefSubtype);
|
||||
}
|
||||
final String localeString = elems[0];
|
||||
final String keyboardLayoutSetName = elems[1];
|
||||
final String extraValue = (elems.length == 3) ? elems[2] : null;
|
||||
subtypesArray[i] = AdditionalSubtype.createAdditionalSubtype(
|
||||
localeString, keyboardLayoutSetName, extraValue);
|
||||
subtypesArray[i] = createAdditionalSubtype(prefSubtypeArray[i]);
|
||||
}
|
||||
return subtypesArray;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,438 @@
|
|||
/**
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.preference.DialogPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.util.Pair;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.SpinnerAdapter;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class AdditionalSubtypeSettings extends PreferenceFragment {
|
||||
private SharedPreferences mPrefs;
|
||||
private SubtypeLocaleAdapter mSubtypeLocaleAdapter;
|
||||
private KeyboardLayoutSetAdapter mKeyboardLayoutSetAdapter;
|
||||
|
||||
private PreferenceGroup mSubtypePrefGroup;
|
||||
|
||||
private static final int MENU_ADD_SUBTYPE = Menu.FIRST;
|
||||
|
||||
static class SubtypeLocaleItem extends Pair<String, String>
|
||||
implements Comparable<SubtypeLocaleItem> {
|
||||
public SubtypeLocaleItem(String localeString, String displayName) {
|
||||
super(localeString, displayName);
|
||||
}
|
||||
|
||||
public SubtypeLocaleItem(String localeString) {
|
||||
this(localeString, getDisplayName(localeString));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return second;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(SubtypeLocaleItem o) {
|
||||
return first.compareTo(o.first);
|
||||
}
|
||||
|
||||
private static String getDisplayName(String localeString) {
|
||||
final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
|
||||
return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
|
||||
}
|
||||
}
|
||||
|
||||
static class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
|
||||
public SubtypeLocaleAdapter(Context context) {
|
||||
super(context, android.R.layout.simple_spinner_item);
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
final TreeSet<SubtypeLocaleItem> items = new TreeSet<SubtypeLocaleItem>();
|
||||
final InputMethodInfo imi = ImfUtils.getInputMethodInfoOfThisIme(context);
|
||||
final int count = imi.getSubtypeCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final InputMethodSubtype subtype = imi.getSubtypeAt(i);
|
||||
if (subtype.containsExtraValueKey(LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE)) {
|
||||
items.add(createItem(context, subtype.getLocale()));
|
||||
}
|
||||
}
|
||||
// TODO: Should filter out already existing combinations of locale and layout.
|
||||
addAll(items);
|
||||
}
|
||||
|
||||
public static SubtypeLocaleItem createItem(Context context, String localeString) {
|
||||
if (localeString.equals(SubtypeLocale.NO_LANGUAGE)) {
|
||||
final String displayName = context.getString(R.string.subtype_no_language);
|
||||
return new SubtypeLocaleItem(localeString, displayName);
|
||||
} else {
|
||||
return new SubtypeLocaleItem(localeString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class KeyboardLayoutSetItem extends Pair<String, String> {
|
||||
public KeyboardLayoutSetItem(String keyboardLayoutSetName) {
|
||||
super(keyboardLayoutSetName, getDisplayName(keyboardLayoutSetName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return second;
|
||||
}
|
||||
|
||||
private static String getDisplayName(String keyboardLayoutSetName) {
|
||||
return keyboardLayoutSetName.toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
static class KeyboardLayoutSetAdapter extends ArrayAdapter<KeyboardLayoutSetItem> {
|
||||
public KeyboardLayoutSetAdapter(Context context) {
|
||||
super(context, android.R.layout.simple_spinner_item);
|
||||
setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
// TODO: Should filter out already existing combinations of locale and layout.
|
||||
for (final String layout : AdditionalSubtype.PREDEFINED_KEYBOARD_LAYOUT_SET) {
|
||||
add(new KeyboardLayoutSetItem(layout));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface SubtypeDialogProxy {
|
||||
public void onRemovePressed(SubtypePreference subtypePref);
|
||||
public SubtypeLocaleAdapter getSubtypeLocaleAdapter();
|
||||
public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter();
|
||||
}
|
||||
|
||||
static class SubtypePreference extends DialogPreference {
|
||||
private InputMethodSubtype mSubtype;
|
||||
|
||||
private final SubtypeDialogProxy mProxy;
|
||||
private Spinner mSubtypeLocaleSpinner;
|
||||
private Spinner mKeyboardLayoutSetSpinner;
|
||||
|
||||
public SubtypePreference(Context context, InputMethodSubtype subtype,
|
||||
SubtypeDialogProxy proxy) {
|
||||
super(context, null);
|
||||
setPersistent(false);
|
||||
mProxy = proxy;
|
||||
setSubtype(subtype);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
showDialog(null);
|
||||
}
|
||||
|
||||
public InputMethodSubtype getSubtype() {
|
||||
return mSubtype;
|
||||
}
|
||||
|
||||
public void setSubtype(InputMethodSubtype subtype) {
|
||||
mSubtype = subtype;
|
||||
if (subtype == null) {
|
||||
setTitle(null);
|
||||
setDialogTitle(R.string.add_style);
|
||||
} else {
|
||||
final String displayName = SubtypeLocale.getFullDisplayName(subtype);
|
||||
setTitle(displayName);
|
||||
setDialogTitle(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
||||
final Context context = builder.getContext();
|
||||
final View v = LayoutInflater.from(context).inflate(
|
||||
R.layout.additional_subtype_dialog, null);
|
||||
builder.setView(v);
|
||||
mSubtypeLocaleSpinner = (Spinner) v.findViewById(R.id.subtype_locale_spinner);
|
||||
mSubtypeLocaleSpinner.setAdapter(mProxy.getSubtypeLocaleAdapter());
|
||||
mKeyboardLayoutSetSpinner = (Spinner) v.findViewById(R.id.keyboard_layout_set_spinner);
|
||||
mKeyboardLayoutSetSpinner.setAdapter(mProxy.getKeyboardLayoutSetAdapter());
|
||||
|
||||
if (mSubtype == null) {
|
||||
builder.setPositiveButton(R.string.add, this)
|
||||
.setNegativeButton(android.R.string.cancel, this);
|
||||
} else {
|
||||
builder.setPositiveButton(R.string.save, this)
|
||||
.setNeutralButton(android.R.string.cancel, this)
|
||||
.setNegativeButton(R.string.remove, this);
|
||||
final SubtypeLocaleItem localeItem = SubtypeLocaleAdapter.createItem(
|
||||
context, mSubtype.getLocale());
|
||||
final KeyboardLayoutSetItem layoutItem = new KeyboardLayoutSetItem(
|
||||
SubtypeLocale.getKeyboardLayoutSetName(mSubtype));
|
||||
setSpinnerPosition(mSubtypeLocaleSpinner, localeItem);
|
||||
setSpinnerPosition(mKeyboardLayoutSetSpinner, layoutItem);
|
||||
}
|
||||
}
|
||||
|
||||
private static void setSpinnerPosition(Spinner spinner, Object itemToSelect) {
|
||||
final SpinnerAdapter adapter = spinner.getAdapter();
|
||||
final int count = adapter.getCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final Object item = spinner.getItemAtPosition(i);
|
||||
if (item.equals(itemToSelect)) {
|
||||
spinner.setSelection(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
super.onClick(dialog, which);
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
final SubtypeLocaleItem locale =
|
||||
(SubtypeLocaleItem) mSubtypeLocaleSpinner.getSelectedItem();
|
||||
final KeyboardLayoutSetItem layout =
|
||||
(KeyboardLayoutSetItem) mKeyboardLayoutSetSpinner.getSelectedItem();
|
||||
final InputMethodSubtype subtype = AdditionalSubtype.createAdditionalSubtype(
|
||||
locale.first, layout.first, LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
|
||||
setSubtype(subtype);
|
||||
notifyChanged();
|
||||
break;
|
||||
case DialogInterface.BUTTON_NEUTRAL:
|
||||
// Nothing to do
|
||||
break;
|
||||
case DialogInterface.BUTTON_NEGATIVE:
|
||||
mProxy.onRemovePressed(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
final SavedState myState = new SavedState(super.onSaveInstanceState());
|
||||
myState.mSubtype = mSubtype;
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof SavedState) {
|
||||
final SavedState myState = (SavedState) state;
|
||||
super.onRestoreInstanceState(state);
|
||||
setSubtype(myState.mSubtype);
|
||||
} else {
|
||||
super.onRestoreInstanceState(state);
|
||||
}
|
||||
}
|
||||
|
||||
static class SavedState extends Preference.BaseSavedState {
|
||||
InputMethodSubtype mSubtype;
|
||||
private static final byte VALID = 1;
|
||||
private static final byte INVALID = 0;
|
||||
|
||||
public SavedState(Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
if (mSubtype != null) {
|
||||
dest.writeByte(VALID);
|
||||
mSubtype.writeToParcel(dest, 0);
|
||||
} else {
|
||||
dest.writeByte(INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
public SavedState(Parcel source) {
|
||||
super(source);
|
||||
if (source.readByte() == VALID) {
|
||||
mSubtype = source.readParcelable(null);
|
||||
} else {
|
||||
mSubtype = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<SavedState> CREATOR =
|
||||
new Parcelable.Creator<SavedState>() {
|
||||
@Override
|
||||
public SavedState createFromParcel(Parcel source) {
|
||||
return new SavedState(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public AdditionalSubtypeSettings() {
|
||||
// Empty constructor for fragment generation.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.additional_subtype_settings);
|
||||
setHasOptionsMenu(true);
|
||||
mSubtypePrefGroup = getPreferenceScreen();
|
||||
|
||||
mPrefs = getPreferenceManager().getSharedPreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
final Context context = getActivity();
|
||||
mSubtypeLocaleAdapter = new SubtypeLocaleAdapter(context);
|
||||
mKeyboardLayoutSetAdapter = new KeyboardLayoutSetAdapter(context);
|
||||
|
||||
// TODO: Restore editing dialog if any.
|
||||
}
|
||||
|
||||
private final SubtypeDialogProxy mSubtypeProxy = new SubtypeDialogProxy() {
|
||||
@Override
|
||||
public void onRemovePressed(SubtypePreference subtypePref) {
|
||||
final PreferenceGroup group = mSubtypePrefGroup;
|
||||
if (group != null) {
|
||||
group.removePreference(subtypePref);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubtypeLocaleAdapter getSubtypeLocaleAdapter() {
|
||||
return mSubtypeLocaleAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyboardLayoutSetAdapter getKeyboardLayoutSetAdapter() {
|
||||
return mKeyboardLayoutSetAdapter;
|
||||
}
|
||||
};
|
||||
|
||||
private void setPrefSubtypes(String prefSubtypes, Context context) {
|
||||
final PreferenceGroup group = mSubtypePrefGroup;
|
||||
group.removeAll();
|
||||
final String[] prefSubtypeArray = prefSubtypes.split(
|
||||
AdditionalSubtype.PREF_SUBTYPE_SEPARATOR);
|
||||
for (final String prefSubtype : prefSubtypeArray) {
|
||||
final InputMethodSubtype subtype =
|
||||
AdditionalSubtype.createAdditionalSubtype(prefSubtype);
|
||||
final SubtypePreference pref = new SubtypePreference(
|
||||
context, subtype, mSubtypeProxy);
|
||||
group.addPreference(pref);
|
||||
}
|
||||
}
|
||||
|
||||
private String getPrefSubtypes() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int count = mSubtypePrefGroup.getPreferenceCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final Preference pref = mSubtypePrefGroup.getPreference(i);
|
||||
if (pref instanceof SubtypePreference) {
|
||||
final InputMethodSubtype subtype = ((SubtypePreference)pref).getSubtype();
|
||||
if (sb.length() > 0) {
|
||||
sb.append(AdditionalSubtype.PREF_SUBTYPE_SEPARATOR);
|
||||
}
|
||||
sb.append(AdditionalSubtype.getPrefSubtype(subtype));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
final String prefSubtypes =
|
||||
SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources());
|
||||
setPrefSubtypes(prefSubtypes, getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
final String oldSubtypes = SettingsValues.getPrefAdditionalSubtypes(mPrefs, getResources());
|
||||
final String prefSubtypes = getPrefSubtypes();
|
||||
if (prefSubtypes.equals(oldSubtypes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SharedPreferences.Editor editor = mPrefs.edit();
|
||||
try {
|
||||
editor.putString(Settings.PREF_CUSTOM_INPUT_STYLES, prefSubtypes);
|
||||
} finally {
|
||||
editor.apply();
|
||||
}
|
||||
final InputMethodSubtype[] subtypes =
|
||||
AdditionalSubtype.createAdditionalSubtypesArray(prefSubtypes);
|
||||
ImfUtils.setAdditionalInputMethodSubtypes(getActivity(), subtypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
// TODO: save editing dialog state.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen prefScreen, Preference pref) {
|
||||
if (pref instanceof SubtypePreference) {
|
||||
return true;
|
||||
}
|
||||
return super.onPreferenceTreeClick(prefScreen, pref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
final MenuItem addSubtypeMenu = menu.add(0, MENU_ADD_SUBTYPE, 0, R.string.add_style);
|
||||
addSubtypeMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
final int itemId = item.getItemId();
|
||||
if (itemId == MENU_ADD_SUBTYPE) {
|
||||
final SubtypePreference subtypePref = new SubtypePreference(
|
||||
getActivity(), null, mSubtypeProxy);
|
||||
mSubtypePrefGroup.addPreference(subtypePref);
|
||||
subtypePref.show();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ import android.preference.PreferenceGroup;
|
|||
import android.preference.PreferenceScreen;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||
import android.widget.TextView;
|
||||
|
@ -255,6 +256,7 @@ public class Settings extends InputMethodSettingsFragment
|
|||
}
|
||||
updateShowCorrectionSuggestionsSummary();
|
||||
updateKeyPreviewPopupDelaySummary();
|
||||
updateCustomInputStylesSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -294,6 +296,21 @@ public class Settings extends InputMethodSettingsFragment
|
|||
mShowCorrectionSuggestionsPreference.getValue())]);
|
||||
}
|
||||
|
||||
private void updateCustomInputStylesSummary() {
|
||||
final PreferenceScreen customInputStyles =
|
||||
(PreferenceScreen)findPreference(PREF_CUSTOM_INPUT_STYLES);
|
||||
final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
|
||||
final String prefSubtype = SettingsValues.getPrefAdditionalSubtypes(prefs, getResources());
|
||||
final InputMethodSubtype[] subtypes =
|
||||
AdditionalSubtype.createAdditionalSubtypesArray(prefSubtype);
|
||||
final StringBuilder styles = new StringBuilder();
|
||||
for (final InputMethodSubtype subtype : subtypes) {
|
||||
if (styles.length() > 0) styles.append(", ");
|
||||
styles.append(SubtypeLocale.getFullDisplayName(subtype));
|
||||
}
|
||||
customInputStyles.setSummary(styles);
|
||||
}
|
||||
|
||||
private void updateKeyPreviewPopupDelaySummary() {
|
||||
final ListPreference lp = mKeyPreviewPopupDismissDelay;
|
||||
lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]);
|
||||
|
|
|
@ -20,11 +20,15 @@ import android.content.Intent;
|
|||
import android.preference.PreferenceActivity;
|
||||
|
||||
public class SettingsActivity extends PreferenceActivity {
|
||||
private static final String DEFAULT_FRAGMENT = Settings.class.getName();
|
||||
|
||||
@Override
|
||||
public Intent getIntent() {
|
||||
final Intent modIntent = new Intent(super.getIntent());
|
||||
modIntent.putExtra(EXTRA_SHOW_FRAGMENT, Settings.class.getName());
|
||||
modIntent.putExtra(EXTRA_NO_HEADERS, true);
|
||||
return modIntent;
|
||||
final Intent intent = super.getIntent();
|
||||
if (!intent.hasExtra(EXTRA_SHOW_FRAGMENT)) {
|
||||
intent.putExtra(EXTRA_SHOW_FRAGMENT, DEFAULT_FRAGMENT);
|
||||
}
|
||||
intent.putExtra(EXTRA_NO_HEADERS, true);
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* When you call the constructor of this class, you may want to change the current system locale by
|
||||
|
@ -148,7 +147,6 @@ public class SettingsValues {
|
|||
mAutoCorrectionThresholdRawValue);
|
||||
mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff);
|
||||
mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain);
|
||||
|
||||
mAdditionalSubtypes = AdditionalSubtype.createAdditionalSubtypesArray(
|
||||
getPrefAdditionalSubtypes(prefs, res));
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import java.util.HashMap;
|
|||
import java.util.Locale;
|
||||
|
||||
public class SubtypeLocale {
|
||||
private static final String TAG = SubtypeLocale.class.getSimpleName();
|
||||
|
||||
// Special language code to represent "no language".
|
||||
public static final String NO_LANGUAGE = "zz";
|
||||
|
||||
|
@ -56,26 +58,29 @@ public class SubtypeLocale {
|
|||
// zz qwerty F QWERTY QWERTY
|
||||
// fr qwertz T Fr Français Français (QWERTZ)
|
||||
// de qwerty T De Deutsch Deutsch (QWERTY)
|
||||
// en azerty T En English English (AZERTY)
|
||||
// en_US azerty T En English English (US) (AZERTY)
|
||||
// zz azerty T AZERTY AZERTY
|
||||
|
||||
// Get InputMethodSubtype's full display name in its locale.
|
||||
public static String getFullDisplayName(InputMethodSubtype subtype) {
|
||||
final String value = sExceptionalDisplayNamesMap.get(subtype.getLocale());
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (isNoLanguage(subtype)) {
|
||||
return getKeyboardLayoutSetDisplayName(subtype);
|
||||
}
|
||||
|
||||
final String exceptionalValue = sExceptionalDisplayNamesMap.get(subtype.getLocale());
|
||||
|
||||
final Locale locale = getSubtypeLocale(subtype);
|
||||
final String language = StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
|
||||
if (AdditionalSubtype.isAdditionalSubtype(subtype)) {
|
||||
return String.format("%s (%s)",
|
||||
language, getKeyboardLayoutSetDisplayName(subtype));
|
||||
final String language = (exceptionalValue != null) ? exceptionalValue
|
||||
: StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale);
|
||||
final String layout = getKeyboardLayoutSetDisplayName(subtype);
|
||||
return String.format("%s (%s)", language, layout);
|
||||
}
|
||||
|
||||
if (exceptionalValue != null) {
|
||||
return exceptionalValue;
|
||||
}
|
||||
|
||||
return StringUtils.toTitleCase(locale.getDisplayName(locale), locale);
|
||||
}
|
||||
|
||||
|
@ -116,7 +121,11 @@ public class SubtypeLocale {
|
|||
LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET);
|
||||
// TODO: Remove this null check when InputMethodManager.getCurrentInputMethodSubtype is
|
||||
// fixed.
|
||||
if (keyboardLayoutSet == null) return AdditionalSubtype.QWERTY;
|
||||
if (keyboardLayoutSet == null) {
|
||||
android.util.Log.w(TAG, "KeyboardLayoutSet not found, use QWERTY: " +
|
||||
getFullDisplayName(subtype) + " extraValue=" + subtype.getExtraValue());
|
||||
return AdditionalSubtype.QWERTY;
|
||||
}
|
||||
return keyboardLayoutSet;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@ public class SubtypeLocaleTests extends AndroidTestCase {
|
|||
// zz qwerty F QWERTY QWERTY
|
||||
// fr qwertz T Fr Français Français (QWERTZ)
|
||||
// de qwerty T De Deutsch Deutsch (QWERTY)
|
||||
// en_US azerty T En English English (US) (AZERTY)
|
||||
// zz azerty T AZERTY AZERTY
|
||||
|
||||
public void testSampleSubtypes() {
|
||||
|
@ -168,29 +169,33 @@ public class SubtypeLocaleTests extends AndroidTestCase {
|
|||
Locale.GERMAN.toString(), AdditionalSubtype.QWERTY, null);
|
||||
final InputMethodSubtype FR_QWERTZ = AdditionalSubtype.createAdditionalSubtype(
|
||||
Locale.FRENCH.toString(), AdditionalSubtype.QWERTZ, null);
|
||||
final InputMethodSubtype EN_AZERTY = AdditionalSubtype.createAdditionalSubtype(
|
||||
Locale.ENGLISH.toString(), AdditionalSubtype.AZERTY, null);
|
||||
final InputMethodSubtype US_AZERTY = AdditionalSubtype.createAdditionalSubtype(
|
||||
Locale.US.toString(), AdditionalSubtype.AZERTY, null);
|
||||
final InputMethodSubtype ZZ_AZERTY = AdditionalSubtype.createAdditionalSubtype(
|
||||
SubtypeLocale.NO_LANGUAGE, AdditionalSubtype.AZERTY, null);
|
||||
|
||||
assertTrue(AdditionalSubtype.isAdditionalSubtype(FR_QWERTZ));
|
||||
assertTrue(AdditionalSubtype.isAdditionalSubtype(DE_QWERTY));
|
||||
assertTrue(AdditionalSubtype.isAdditionalSubtype(EN_AZERTY));
|
||||
assertTrue(AdditionalSubtype.isAdditionalSubtype(US_AZERTY));
|
||||
assertTrue(AdditionalSubtype.isAdditionalSubtype(ZZ_AZERTY));
|
||||
|
||||
assertEquals("fr qwertz", "Français (QWERTZ)", SubtypeLocale.getFullDisplayName(FR_QWERTZ));
|
||||
assertEquals("de qwerty", "Deutsch (QWERTY)", SubtypeLocale.getFullDisplayName(DE_QWERTY));
|
||||
assertEquals("en azerty", "English (AZERTY)", SubtypeLocale.getFullDisplayName(EN_AZERTY));
|
||||
assertEquals("zz azerty", "AZERTY", SubtypeLocale.getFullDisplayName(ZZ_AZERTY));
|
||||
assertEquals("fr qwertz", "Français (QWERTZ)",
|
||||
SubtypeLocale.getFullDisplayName(FR_QWERTZ));
|
||||
assertEquals("de qwerty", "Deutsch (QWERTY)",
|
||||
SubtypeLocale.getFullDisplayName(DE_QWERTY));
|
||||
assertEquals("en_US azerty", "English (US) (AZERTY)",
|
||||
SubtypeLocale.getFullDisplayName(US_AZERTY));
|
||||
assertEquals("zz azerty", "AZERTY",
|
||||
SubtypeLocale.getFullDisplayName(ZZ_AZERTY));
|
||||
|
||||
assertEquals("fr qwertz", "Français", SubtypeLocale.getMiddleDisplayName(FR_QWERTZ));
|
||||
assertEquals("de qwerty", "Deutsch", SubtypeLocale.getMiddleDisplayName(DE_QWERTY));
|
||||
assertEquals("en azerty", "English", SubtypeLocale.getMiddleDisplayName(EN_AZERTY));
|
||||
assertEquals("zz azerty", "AZERTY", SubtypeLocale.getMiddleDisplayName(ZZ_AZERTY));
|
||||
assertEquals("fr qwertz", "Français", SubtypeLocale.getMiddleDisplayName(FR_QWERTZ));
|
||||
assertEquals("de qwerty", "Deutsch", SubtypeLocale.getMiddleDisplayName(DE_QWERTY));
|
||||
assertEquals("en_US azerty", "English", SubtypeLocale.getMiddleDisplayName(US_AZERTY));
|
||||
assertEquals("zz azerty", "AZERTY", SubtypeLocale.getMiddleDisplayName(ZZ_AZERTY));
|
||||
|
||||
assertEquals("fr qwertz", "Fr", SubtypeLocale.getShortDisplayName(FR_QWERTZ));
|
||||
assertEquals("de qwerty", "De", SubtypeLocale.getShortDisplayName(DE_QWERTY));
|
||||
assertEquals("en azerty", "En", SubtypeLocale.getShortDisplayName(EN_AZERTY));
|
||||
assertEquals("zz azerty", "", SubtypeLocale.getShortDisplayName(ZZ_AZERTY));
|
||||
assertEquals("fr qwertz", "Fr", SubtypeLocale.getShortDisplayName(FR_QWERTZ));
|
||||
assertEquals("de qwerty", "De", SubtypeLocale.getShortDisplayName(DE_QWERTY));
|
||||
assertEquals("en_US azerty", "En", SubtypeLocale.getShortDisplayName(US_AZERTY));
|
||||
assertEquals("zz azerty", "", SubtypeLocale.getShortDisplayName(ZZ_AZERTY));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue