diff options
author | satok <satok@google.com> | 2010-12-15 04:57:24 +0900 |
---|---|---|
committer | satok <satok@google.com> | 2010-12-17 18:32:36 +0900 |
commit | c88a7ff1efd10374974e45768bde1658cc1d8483 (patch) | |
tree | c3b99796891021602f229f666147bd2e9cafc5fb /src/com | |
parent | 9be84b15961e0ef452c8f859ffe1ba57581bb473 (diff) | |
download | packages_apps_Settings-c88a7ff1efd10374974e45768bde1658cc1d8483.tar.gz packages_apps_Settings-c88a7ff1efd10374974e45768bde1658cc1d8483.tar.bz2 packages_apps_Settings-c88a7ff1efd10374974e45768bde1658cc1d8483.zip |
Implement new design for settings of InputMethods
Change-Id: I82392e4a028abe2d588622a7e89fd035966f603a
Diffstat (limited to 'src/com')
5 files changed, 460 insertions, 243 deletions
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index b91c7ee00..280f29577 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -302,6 +302,7 @@ public class Settings extends PreferenceActivity { public static class StorageSettingsActivity extends Settings { } public static class WifiSettingsActivity extends Settings { } public static class InputMethodAndLanguageSettingsActivity extends Settings { } + public static class InputMethodConfigActivity extends Settings { } public static class InputMethodAndSubtypeEnablerActivity extends Settings { } public static class LocalePickerActivity extends Settings { } public static class UserDictionarySettingsActivity extends Settings { } diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java index ef5920102..117bec5d2 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java +++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java @@ -26,127 +26,74 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.Bundle; import android.preference.CheckBoxPreference; +import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; +import android.provider.Settings; import android.text.TextUtils; +import android.util.Log; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment { +public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment + implements Preference.OnPreferenceChangeListener{ private static final String KEY_PHONE_LANGUAGE = "phone_language"; - private static final String KEY_INPUT_METHOD = "input_method"; - private static final String KEY_KEYBOARD_SETTINGS_CATEGORY = "keyboard_settings_category"; - private static final String KEY_HARDKEYBOARD_CATEGORY = "hardkeyboard_category"; - private boolean mHaveHardKeyboard; + private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method"; + private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector"; - private List<InputMethodInfo> mInputMethodProperties; - private List<CheckBoxPreference> mCheckboxes; + private int mDefaultInputMethodSelectorVisibility = 0; + private ListPreference mShowInputMethodSelectorPref; private Preference mLanguagePref; - final TextUtils.SimpleStringSplitter mStringColonSplitter - = new TextUtils.SimpleStringSplitter(':'); - - private AlertDialog mDialog = null; - - static public String getInputMethodIdFromKey(String key) { - return key; - } - @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.language_settings); - if (getActivity().getAssets().getLocales().length == 1) { - getPreferenceScreen(). - removePreference(findPreference(KEY_PHONE_LANGUAGE)); - } else { - mLanguagePref = findPreference(KEY_PHONE_LANGUAGE); + try { + mDefaultInputMethodSelectorVisibility = Integer.valueOf( + getString(R.string.input_method_selector_visibility_default_value)); + } catch (NumberFormatException e) { } - Configuration config = getResources().getConfiguration(); - if (config.keyboard != Configuration.KEYBOARD_QWERTY) { - getPreferenceScreen().removePreference( - getPreferenceScreen().findPreference(KEY_HARDKEYBOARD_CATEGORY)); + if (getActivity().getAssets().getLocales().length == 1) { + // No "Select language" pref if there's only one system locale available. + getPreferenceScreen().removePreference(findPreference(KEY_PHONE_LANGUAGE)); } else { - mHaveHardKeyboard = true; + mLanguagePref = findPreference(KEY_PHONE_LANGUAGE); } - mCheckboxes = new ArrayList<CheckBoxPreference>(); - onCreateIMM(); + mShowInputMethodSelectorPref = (ListPreference)findPreference( + KEY_INPUT_METHOD_SELECTOR); + mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); + // TODO: Update current input method name on summary + updateInputMethodSelectorSummary(loadInputMethodSelectorVisibility()); new VoiceInputOutputSettings(this).onCreate(); } - private boolean isSystemIme(InputMethodInfo property) { - return (property.getServiceInfo().applicationInfo.flags - & ApplicationInfo.FLAG_SYSTEM) != 0; - } - - private void onCreateIMM() { - InputMethodManager imm = (InputMethodManager) getSystemService( - Context.INPUT_METHOD_SERVICE); - - mInputMethodProperties = imm.getInputMethodList(); - - PreferenceGroup keyboardSettingsCategory = (PreferenceGroup) findPreference( - KEY_KEYBOARD_SETTINGS_CATEGORY); - - int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties - .size()); - for (int i = 0; i < N; ++i) { - InputMethodInfo property = mInputMethodProperties.get(i); - String prefKey = property.getId(); - - CharSequence label = property.loadLabel(getActivity().getPackageManager()); - boolean systemIME = isSystemIme(property); - // Add a check box. - // Don't show the toggle if it's the only keyboard in the system, or it's a system IME. - if (mHaveHardKeyboard || (N > 1 && !systemIME)) { - CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity()); - chkbxPref.setKey(prefKey); - chkbxPref.setTitle(label); - keyboardSettingsCategory.addPreference(chkbxPref); - mCheckboxes.add(chkbxPref); - } - - // If setting activity is available, add a setting screen entry. - if (null != property.getSettingsActivity()) { - PreferenceScreen prefScreen = new PreferenceScreen(getActivity(), null); - String settingsActivity = property.getSettingsActivity(); - if (settingsActivity.lastIndexOf("/") < 0) { - settingsActivity = property.getPackageName() + "/" + settingsActivity; - } - prefScreen.setKey(settingsActivity); - prefScreen.setTitle(label); - if (N == 1) { - prefScreen.setSummary(getResources().getString( - R.string.onscreen_keyboard_settings_summary)); - } else { - CharSequence settingsLabel = getResources().getString( - R.string.input_methods_settings_label_format, label); - prefScreen.setSummary(settingsLabel); - } - keyboardSettingsCategory.addPreference(prefScreen); - } + private void updateInputMethodSelectorSummary(int value) { + String[] inputMethodSelectorTitles = getResources().getStringArray( + R.array.input_method_selector_titles); + if (inputMethodSelectorTitles.length > value) { + mShowInputMethodSelectorPref.setSummary(inputMethodSelectorTitles[value]); + mShowInputMethodSelectorPref.setValue(String.valueOf(value)); } } @Override public void onResume() { super.onResume(); - - InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( - this, getContentResolver(), mInputMethodProperties); - if (mLanguagePref != null) { Configuration conf = getResources().getConfiguration(); String locale = conf.locale.getDisplayName(conf.locale); @@ -155,107 +102,58 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment { mLanguagePref.setSummary(locale); } } + + mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); } @Override public void onPause() { super.onPause(); - InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(), - mInputMethodProperties, mHaveHardKeyboard); + mShowInputMethodSelectorPref.setOnPreferenceChangeListener(null); } @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { - // Input Method stuff if (Utils.isMonkeyRunning()) { return false; } - - if (preference instanceof CheckBoxPreference) { - final CheckBoxPreference chkPref = (CheckBoxPreference) preference; - final String id = getInputMethodIdFromKey(chkPref.getKey()); - if (chkPref.isChecked()) { - InputMethodInfo selImi = null; - final int N = mInputMethodProperties.size(); - for (int i=0; i<N; i++) { - InputMethodInfo imi = mInputMethodProperties.get(i); - if (id.equals(imi.getId())) { - selImi = imi; - if (isSystemIme(imi)) { - // This is a built-in IME, so no need to warn. - return super.onPreferenceTreeClick(preferenceScreen, preference); - } - } - } - chkPref.setChecked(false); - if (selImi == null) { - return super.onPreferenceTreeClick(preferenceScreen, preference); - } - if (mDialog == null) { - // TODO: DialogFragment? - mDialog = (new AlertDialog.Builder(getActivity())) - .setTitle(android.R.string.dialog_alert_title) - .setIcon(android.R.drawable.ic_dialog_alert) - .setCancelable(true) - .setPositiveButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - chkPref.setChecked(true); - } - - }) - .setNegativeButton(android.R.string.cancel, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - } - - }) - .create(); - } else { - if (mDialog.isShowing()) { - mDialog.dismiss(); - } - } - mDialog.setMessage(getResources().getString( - R.string.ime_security_warning, - selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager()))); - mDialog.show(); - } - } else if (preference instanceof PreferenceScreen) { + if (preference instanceof PreferenceScreen) { if (preference.getFragment() != null) { // Fragment will be handled correctly by the super class. - } else if (KEY_INPUT_METHOD.equals(preference.getKey())) { + } else if (KEY_CURRENT_INPUT_METHOD.equals(preference.getKey())) { final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showInputMethodPicker(); - } else if (preference.getIntent() == null) { - PreferenceScreen pref = (PreferenceScreen) preference; - String activityName = pref.getKey(); - String packageName = activityName.substring(0, activityName - .lastIndexOf(".")); - int slash = activityName.indexOf("/"); - if (slash > 0) { - packageName = activityName.substring(0, slash); - activityName = activityName.substring(slash + 1); - } - if (activityName.length() > 0) { - Intent i = new Intent(Intent.ACTION_MAIN); - i.setClassName(packageName, activityName); - startActivity(i); - } } } return super.onPreferenceTreeClick(preferenceScreen, preference); } + private void saveInputMethodSelectorVisibility(String value) { + try { + int intValue = Integer.valueOf(value); + Settings.Secure.putInt(getContentResolver(), + Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY, intValue); + updateInputMethodSelectorSummary(intValue); + } catch(NumberFormatException e) { + } + } + + private int loadInputMethodSelectorVisibility() { + return Settings.Secure.getInt(getContentResolver(), + Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY, + mDefaultInputMethodSelectorVisibility); + } + @Override - public void onDestroy() { - super.onDestroy(); - if (mDialog != null) { - mDialog.dismiss(); - mDialog = null; + public boolean onPreferenceChange(Preference preference, Object value) { + if (preference == mShowInputMethodSelectorPref) { + if (value instanceof String) { + saveInputMethodSelectorVisibility((String)value); + } } + return false; } } diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java index cb9051428..c2c0a0704 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java +++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeEnabler.java @@ -29,26 +29,32 @@ import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; +import android.text.TextUtils; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment { - private boolean mHaveHardKeyboard; - - private List<InputMethodInfo> mInputMethodProperties; + public static final String EXTRA_INPUT_METHOD_ID = "input_method_id"; private AlertDialog mDialog = null; + private boolean mHaveHardKeyboard; + final private HashMap<String, List<Preference>> mInputMethodPrefsMap = + new HashMap<String, List<Preference>>(); + private List<InputMethodInfo> mInputMethodProperties; + private String mInputMethodId; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); Configuration config = getResources().getConfiguration(); mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY); + mInputMethodId = getActivity().getIntent().getStringExtra(EXTRA_INPUT_METHOD_ID); onCreateIMM(); setPreferenceScreen(createPreferenceHierarchy()); } @@ -57,7 +63,7 @@ public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment { public void onResume() { super.onResume(); InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( - this, getContentResolver(), mInputMethodProperties); + this, getContentResolver(), mInputMethodProperties, mInputMethodPrefsMap); } @Override @@ -156,53 +162,48 @@ public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment { PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity()); int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size()); - // TODO: Use iterator. + for (int i = 0; i < N; ++i) { + final InputMethodInfo imi = mInputMethodProperties.get(i); + if (imi.getSubtypes().size() <= 1) continue; + String imiId = imi.getId(); + // Add to this subtype the list when no IME is specified or when the IME of this + // subtype is the specified IME. + if (!TextUtils.isEmpty(mInputMethodId) && !mInputMethodId.equals(imiId)) { + continue; + } PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(getActivity()); root.addPreference(keyboardSettingsCategory); - InputMethodInfo property = mInputMethodProperties.get(i); - String prefKey = property.getId(); PackageManager pm = getPackageManager(); - CharSequence label = property.loadLabel(pm); - boolean systemIME = InputMethodAndSubtypeUtil.isSystemIme(property); - - keyboardSettingsCategory.setTitle(label); - - // Add a check box. - // Don't show the toggle if it's the only keyboard in the system, or it's a system IME. - if (mHaveHardKeyboard || (N > 1 && !systemIME)) { - CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity()); - chkbxPref.setKey(prefKey); - chkbxPref.setTitle(label); - keyboardSettingsCategory.addPreference(chkbxPref); - } + CharSequence label = imi.loadLabel(pm); + + keyboardSettingsCategory.setTitle(getResources().getString( + R.string.input_methods_and_subtype_enabler_title_format, label)); + keyboardSettingsCategory.setKey(imiId); - ArrayList<InputMethodSubtype> subtypes = property.getSubtypes(); + ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes(); + ArrayList<Preference> subtypePreferences = new ArrayList<Preference>(); if (subtypes.size() > 0) { - PreferenceCategory subtypesCategory = new PreferenceCategory(getActivity()); - subtypesCategory.setTitle(getResources().getString( - R.string.input_methods_and_subtype_enabler_title_format, label)); - root.addPreference(subtypesCategory); for (InputMethodSubtype subtype: subtypes) { CharSequence subtypeLabel; int nameResId = subtype.getNameResId(); if (nameResId != 0) { - subtypeLabel = pm.getText(property.getPackageName(), nameResId, - property.getServiceInfo().applicationInfo); + subtypeLabel = pm.getText(imi.getPackageName(), nameResId, + imi.getServiceInfo().applicationInfo); } else { String mode = subtype.getMode(); CharSequence language = subtype.getLocale(); - // TODO: Use more friendly Title and UI subtypeLabel = (mode == null ? "" : mode) + "," + (language == null ? "" : language); } CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity()); - chkbxPref.setKey(prefKey + subtype.hashCode()); + chkbxPref.setKey(imiId + subtype.hashCode()); chkbxPref.setTitle(subtypeLabel); - chkbxPref.setSummary(label); - subtypesCategory.addPreference(chkbxPref); + keyboardSettingsCategory.addPreference(chkbxPref); + subtypePreferences.add(chkbxPref); } + mInputMethodPrefsMap.put(imiId, subtypePreferences); } } return root; diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java index 288e6c26f..460bc9c43 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java +++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java @@ -21,6 +21,7 @@ import com.android.settings.SettingsPreferenceFragment; import android.content.ContentResolver; import android.content.pm.ApplicationInfo; import android.preference.CheckBoxPreference; +import android.preference.Preference; import android.preference.PreferenceScreen; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; @@ -32,6 +33,7 @@ import android.view.inputmethod.InputMethodSubtype; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; public class InputMethodAndSubtypeUtil { @@ -48,6 +50,42 @@ public class InputMethodAndSubtypeUtil { private static final TextUtils.SimpleStringSplitter sStringInputMethodSubtypeSplitter = new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER); + private static void buildEnabledInputMethodsString( + StringBuilder builder, String imi, HashSet<String> subtypes) { + builder.append(imi); + // Inputmethod and subtypes are saved in the settings as follows: + // ime0;subtype0;subtype1:ime1;subtype0:ime2:ime3;subtype0;subtype1 + for (String subtypeId: subtypes) { + builder.append(INPUT_METHOD_SUBTYPE_SEPARATER).append(subtypeId); + } + } + + public static void buildInputMethodsAndSubtypesString( + StringBuilder builder, HashMap<String, HashSet<String>> imsList) { + boolean needsAppendSeparator = false; + for (String imi: imsList.keySet()) { + if (needsAppendSeparator) { + builder.append(INPUT_METHOD_SEPARATER); + } else { + needsAppendSeparator = true; + } + buildEnabledInputMethodsString(builder, imi, imsList.get(imi)); + } + } + + public static void buildDisabledSystemInputMethods( + StringBuilder builder, HashSet<String> imes) { + boolean needsAppendSeparator = false; + for (String ime: imes) { + if (needsAppendSeparator) { + builder.append(INPUT_METHOD_SEPARATER); + } else { + needsAppendSeparator = true; + } + builder.append(ime); + } + } + private static int getInputMethodSubtypeSelected(ContentResolver resolver) { try { return Settings.Secure.getInt(resolver, @@ -96,82 +134,117 @@ public class InputMethodAndSubtypeUtil { return imsList; } - public static void saveInputMethodSubtypeList( - SettingsPreferenceFragment context, ContentResolver resolver, - List<InputMethodInfo> inputMethodProperties, boolean hasHardKeyboard) { + private static HashSet<String> getDisabledSystemIMEs(ContentResolver resolver) { + HashSet<String> set = new HashSet<String>(); + String disabledIMEsStr = Settings.Secure.getString( + resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS); + sStringInputMethodSplitter.setString(disabledIMEsStr); + while(sStringInputMethodSplitter.hasNext()) { + set.add(sStringInputMethodSplitter.next()); + } + return set; + } + + public static void saveInputMethodSubtypeList(SettingsPreferenceFragment context, + ContentResolver resolver, List<InputMethodInfo> inputMethodInfos, + boolean hasHardKeyboard) { String currentInputMethodId = Settings.Secure.getString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD); final int selectedInputMethodSubtype = getInputMethodSubtypeSelected(resolver); + HashMap<String, HashSet<String>> enabledIMEAndSubtypesMap = + getEnabledInputMethodsAndSubtypeList(resolver); + HashSet<String> disabledSystemIMEs = getDisabledSystemIMEs(resolver); - StringBuilder builder = new StringBuilder(); - StringBuilder disabledSysImes = new StringBuilder(); - int firstSubtypeHashCode = NOT_A_SUBTYPE_ID; - - final boolean onlyOneIME = inputMethodProperties.size() == 1; - boolean existsSelectedIME = false; - for (InputMethodInfo property : inputMethodProperties) { - final String id = property.getId(); - CheckBoxPreference pref = (CheckBoxPreference) context.findPreference(id); - boolean isCurrentInputMethod = id.equals(currentInputMethodId); - boolean systemIme = isSystemIme(property); - // TODO: Append subtypes by using the separator ";" - if (((onlyOneIME || systemIme) && !hasHardKeyboard) - || (pref != null && pref.isChecked())) { - if (builder.length() > 0) builder.append(INPUT_METHOD_SEPARATER); - builder.append(id); - for (InputMethodSubtype subtype : property.getSubtypes()) { + final boolean onlyOneIME = inputMethodInfos.size() == 1; + boolean existsSelectedSubtype = false; + for (InputMethodInfo imi : inputMethodInfos) { + final String imiId = imi.getId(); + Preference pref = context.findPreference(imiId); + if (pref == null) continue; + // In the Configure input method screen or in the subtype enabler screen. + // pref is instance of CheckBoxPreference in the Configure input method screen. + final boolean isImeChecked = (pref instanceof CheckBoxPreference) ? + ((CheckBoxPreference) pref).isChecked() + : enabledIMEAndSubtypesMap.containsKey(imiId); + boolean isCurrentInputMethod = imiId.equals(currentInputMethodId); + boolean systemIme = isSystemIme(imi); + if (((onlyOneIME || systemIme) && !hasHardKeyboard) || isImeChecked) { + if (!enabledIMEAndSubtypesMap.containsKey(imiId)) { + // imiId has just been enabled + enabledIMEAndSubtypesMap.put(imiId, new HashSet<String>()); + } + HashSet<String> subtypesSet = enabledIMEAndSubtypesMap.get(imiId); + for (InputMethodSubtype subtype : imi.getSubtypes()) { + final String subtypeHashCodeStr = String.valueOf(subtype.hashCode()); CheckBoxPreference subtypePref = (CheckBoxPreference) context.findPreference( - id + subtype.hashCode()); - if (subtypePref != null && subtypePref.isChecked()) { - builder.append(INPUT_METHOD_SUBTYPE_SEPARATER).append(subtype.hashCode()); + imiId + subtypeHashCodeStr); + // In the Configure input method screen which does not have subtype preferences. + if (subtypePref == null) continue; + if (subtypePref.isChecked()) { + subtypesSet.add(subtypeHashCodeStr); if (isCurrentInputMethod) { if (selectedInputMethodSubtype == subtype.hashCode()) { - existsSelectedIME = true; - } else if (firstSubtypeHashCode == NOT_A_SUBTYPE_ID) { - firstSubtypeHashCode = subtype.hashCode(); + existsSelectedSubtype = true; } } + } else { + subtypesSet.remove(subtypeHashCodeStr); } } - } else if (isCurrentInputMethod) { - // We are processing the current input method, but found that it's not enabled. - // This means that the current input method has been uninstalled. - // If currentInputMethod is already uninstalled, InputMethodManagerService will - // find the applicable IME from the history and the system locale. - if (DEBUG) { - Log.d(TAG, "Current IME was uninstalled or disabled."); + } else { + enabledIMEAndSubtypesMap.remove(imiId); + if (isCurrentInputMethod) { + // We are processing the current input method, but found that it's not enabled. + // This means that the current input method has been uninstalled. + // If currentInputMethod is already uninstalled, InputMethodManagerService will + // find the applicable IME from the history and the system locale. + if (DEBUG) { + Log.d(TAG, "Current IME was uninstalled or disabled."); + } } } // If it's a disabled system ime, add it to the disabled list so that it // doesn't get enabled automatically on any changes to the package list - if (pref != null && !pref.isChecked() && systemIme && hasHardKeyboard) { - if (disabledSysImes.length() > 0) disabledSysImes.append(INPUT_METHOD_SEPARATER); - disabledSysImes.append(id); + if (systemIme && hasHardKeyboard) { + if (disabledSystemIMEs.contains(imiId)) { + if (isImeChecked) { + disabledSystemIMEs.remove(imiId); + } + } else { + if (!isImeChecked) { + disabledSystemIMEs.add(imiId); + } + } } } + StringBuilder builder = new StringBuilder(); + buildInputMethodsAndSubtypesString(builder, enabledIMEAndSubtypesMap); + StringBuilder disabledSysImesBuilder = new StringBuilder(); + buildDisabledSystemInputMethods(disabledSysImesBuilder, disabledSystemIMEs); if (DEBUG) { Log.d(TAG, "--- Save enabled inputmethod settings. :" + builder.toString()); Log.d(TAG, "--- Save disable system inputmethod settings. :" - + disabledSysImes.toString()); + + disabledSysImesBuilder.toString()); Log.d(TAG, "--- Save default inputmethod settings. :" + currentInputMethodId); } // Redefines SelectedSubtype when all subtypes are unchecked or there is no subtype // selected. And if the selected subtype of the current input method was disabled, // We should reset the selected input method's subtype. - if (!existsSelectedIME || !isInputMethodSubtypeSelected(resolver)) { + if (!existsSelectedSubtype || !isInputMethodSubtypeSelected(resolver)) { if (DEBUG) { - Log.d(TAG, "--- Set inputmethod subtype because it's not defined." - + firstSubtypeHashCode); + Log.d(TAG, "--- Reset inputmethod subtype because it's not defined."); } - putSelectedInputMethodSubtype(resolver, firstSubtypeHashCode); + putSelectedInputMethodSubtype(resolver, NOT_A_SUBTYPE_ID); } Settings.Secure.putString(resolver, Settings.Secure.ENABLED_INPUT_METHODS, builder.toString()); - Settings.Secure.putString(resolver, - Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, disabledSysImes.toString()); + if (disabledSysImesBuilder.length() > 0) { + Settings.Secure.putString(resolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, + disabledSysImesBuilder.toString()); + } // If the current input method is unset, InputMethodManagerService will find the applicable // IME from the history and the system locale. Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD, @@ -180,18 +253,25 @@ public class InputMethodAndSubtypeUtil { public static void loadInputMethodSubtypeList( SettingsPreferenceFragment context, ContentResolver resolver, - List<InputMethodInfo> inputMethodProperties) { + List<InputMethodInfo> inputMethodInfos, + final Map<String, List<Preference>> inputMethodPrefsMap) { HashMap<String, HashSet<String>> enabledSubtypes = - getEnabledInputMethodsAndSubtypeList(resolver); + getEnabledInputMethodsAndSubtypeList(resolver); - for (InputMethodInfo property : inputMethodProperties) { - final String id = property.getId(); - CheckBoxPreference pref = (CheckBoxPreference) context.findPreference(id); - if (pref != null) { - boolean isEnabled = enabledSubtypes.containsKey(id); - pref.setChecked(isEnabled); - setSubtypesPreferenceEnabled(context, inputMethodProperties, id, isEnabled); - updateSubtypesPreferenceChecked(context, inputMethodProperties, enabledSubtypes); + for (InputMethodInfo imi : inputMethodInfos) { + final String imiId = imi.getId(); + Preference pref = context.findPreference(imiId); + if (pref != null && pref instanceof CheckBoxPreference) { + CheckBoxPreference checkBoxPreference = (CheckBoxPreference) pref; + boolean isEnabled = enabledSubtypes.containsKey(imiId); + checkBoxPreference.setChecked(isEnabled); + if (inputMethodPrefsMap != null) { + for (Preference childPref: inputMethodPrefsMap.get(imiId)) { + childPref.setEnabled(isEnabled); + } + } + setSubtypesPreferenceEnabled(context, inputMethodInfos, imiId, isEnabled); + updateSubtypesPreferenceChecked(context, inputMethodInfos, enabledSubtypes); } } } diff --git a/src/com/android/settings/inputmethod/InputMethodConfig.java b/src/com/android/settings/inputmethod/InputMethodConfig.java new file mode 100644 index 000000000..640a77333 --- /dev/null +++ b/src/com/android/settings/inputmethod/InputMethodConfig.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2010 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.settings.inputmethod; + +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceScreen; +import android.provider.Settings; +import android.text.TextUtils; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class InputMethodConfig extends SettingsPreferenceFragment { + + private static final String KEY_PHYSICALKEYBOARD_CATEGORY = "hardkeyboard_category"; + private static final String PHYSICALKEYBOARD_SETTINGS_FRAGMENT + = "com.android.settings.PhysicalKeyboardSettings"; + + private AlertDialog mDialog = null; + private boolean mHaveHardKeyboard; + // Map of imi and its preferences + final private HashMap<String, List<Preference>> mInputMethodPrefsMap = + new HashMap<String, List<Preference>>(); + private List<InputMethodInfo> mInputMethodProperties; + + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + Configuration config = getResources().getConfiguration(); + mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY); + InputMethodManager imm = (InputMethodManager) getSystemService( + Context.INPUT_METHOD_SERVICE); + + // TODO: Change mInputMethodProperties to Map + mInputMethodProperties = imm.getInputMethodList(); + setPreferenceScreen(createPreferenceHierarchy()); + } + + @Override + public void onResume() { + super.onResume(); + InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( + this, getContentResolver(), mInputMethodProperties, mInputMethodPrefsMap); + } + + @Override + public void onPause() { + super.onPause(); + InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(), + mInputMethodProperties, mHaveHardKeyboard); + } + + private void showSecurityWarnDialog(InputMethodInfo imi, final CheckBoxPreference chkPref, + final String imiId) { + if (mDialog == null) { + mDialog = (new AlertDialog.Builder(getActivity())) + .setTitle(android.R.string.dialog_alert_title) + .setIcon(android.R.drawable.ic_dialog_alert) + .setCancelable(true) + .setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + chkPref.setChecked(true); + for (Preference pref: mInputMethodPrefsMap.get(imiId)) { + pref.setEnabled(true); + } + } + }) + .setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + } + }) + .create(); + } else { + if (mDialog.isShowing()) { + mDialog.dismiss(); + } + } + mDialog.setMessage(getResources().getString(R.string.ime_security_warning, + imi.getServiceInfo().applicationInfo.loadLabel(getPackageManager()))); + mDialog.show(); + } + + private InputMethodInfo getInputMethodInfoFromImiId(String imiId) { + final int N = mInputMethodProperties.size(); + for (int i = 0; i < N; ++i) { + InputMethodInfo imi = mInputMethodProperties.get(i); + if (imiId.equals(imi.getId())) { + return imi; + } + } + return null; + } + + @Override + public boolean onPreferenceTreeClick( + PreferenceScreen preferenceScreen, Preference preference) { + + if (preference instanceof CheckBoxPreference) { + final CheckBoxPreference chkPref = (CheckBoxPreference) preference; + final String imiId = chkPref.getKey(); + if (chkPref.isChecked()) { + InputMethodInfo selImi = getInputMethodInfoFromImiId(imiId); + if (selImi != null) { + if (InputMethodAndSubtypeUtil.isSystemIme(selImi)) { + // This is a built-in IME, so no need to warn. + return super.onPreferenceTreeClick(preferenceScreen, preference); + } + } else { + return super.onPreferenceTreeClick(preferenceScreen, preference); + } + chkPref.setChecked(false); + showSecurityWarnDialog(selImi, chkPref, imiId); + } else { + for (Preference pref: mInputMethodPrefsMap.get(imiId)) { + pref.setEnabled(false); + } + } + } + return super.onPreferenceTreeClick(preferenceScreen, preference); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mDialog != null) { + mDialog.dismiss(); + mDialog = null; + } + } + + private void addHardKeyboardPreference(PreferenceScreen root) { + PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(getActivity()); + keyboardSettingsCategory.setTitle(R.string.builtin_keyboard_settings_title); + root.addPreference(keyboardSettingsCategory); + PreferenceScreen prefScreen = new PreferenceScreen(getActivity(), null); + prefScreen.setKey(KEY_PHYSICALKEYBOARD_CATEGORY); + prefScreen.setTitle(R.string.builtin_keyboard_settings_title); + prefScreen.setSummary(R.string.builtin_keyboard_settings_summary); + prefScreen.setFragment(PHYSICALKEYBOARD_SETTINGS_FRAGMENT); + } + + private void addInputMethodPreference(PreferenceScreen root, InputMethodInfo imi, + final int imiSize) { + PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(getActivity()); + root.addPreference(keyboardSettingsCategory); + final String imiId = imi.getId(); + mInputMethodPrefsMap.put(imiId, new ArrayList<Preference>()); + + PackageManager pm = getPackageManager(); + CharSequence label = imi.loadLabel(pm); + keyboardSettingsCategory.setTitle(label); + + final boolean isSystemIME = InputMethodAndSubtypeUtil.isSystemIme(imi); + // Add a check box for enabling/disabling IME + CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity()); + chkbxPref.setKey(imiId); + chkbxPref.setTitle(label); + keyboardSettingsCategory.addPreference(chkbxPref); + // Disable the toggle if it's the only keyboard in the system, or it's a system IME. + if (!mHaveHardKeyboard && (imiSize <= 1 || isSystemIME)) { + chkbxPref.setEnabled(false); + } + + Intent intent; + // Add subtype settings when this IME has two or more subtypes. + PreferenceScreen prefScreen = new PreferenceScreen(getActivity(), null); + prefScreen.setTitle(R.string.active_input_method_subtypes); + if (imi.getSubtypes().size() > 1) { + intent = new Intent(Settings.ACTION_INPUT_METHOD_AND_SUBTYPE_ENABLER); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.putExtra(InputMethodAndSubtypeEnabler.EXTRA_INPUT_METHOD_ID, imiId); + prefScreen.setIntent(intent); + keyboardSettingsCategory.addPreference(prefScreen); + mInputMethodPrefsMap.get(imiId).add(prefScreen); + } + + // Add IME settings + String settingsActivity = imi.getSettingsActivity(); + if (!TextUtils.isEmpty(settingsActivity)) { + prefScreen = new PreferenceScreen(getActivity(), null); + prefScreen.setTitle(R.string.input_method_settings); + intent = new Intent(Intent.ACTION_MAIN); + intent.setClassName(imi.getPackageName(), settingsActivity); + prefScreen.setIntent(intent); + keyboardSettingsCategory.addPreference(prefScreen); + mInputMethodPrefsMap.get(imiId).add(prefScreen); + } + } + + private PreferenceScreen createPreferenceHierarchy() { + // Root + PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity()); + if (mHaveHardKeyboard) { + addHardKeyboardPreference(root); + } + + final int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size()); + for (int i = 0; i < N; ++i) { + addInputMethodPreference(root, mInputMethodProperties.get(i), N); + } + return root; + } +} |