diff options
Diffstat (limited to 'src/com/android/settings/inputmethod')
4 files changed, 425 insertions, 308 deletions
diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java index c72f0ba..4ccebf0 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java +++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java @@ -24,14 +24,25 @@ import com.android.settings.VoiceInputOutputSettings; import android.app.Activity; import android.content.Context; +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.ListPreference; import android.preference.Preference; +import android.preference.PreferenceCategory; +import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; import android.provider.Settings; +import android.provider.Settings.System; +import android.text.TextUtils; +import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Set; public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment @@ -40,13 +51,28 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment private static final String KEY_PHONE_LANGUAGE = "phone_language"; private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method"; private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector"; - private static final String KEY_LANGUAGE_SETTINGS_CATEGORY = "language_settings_category"; private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings"; + // false: on ICS or later + private static final boolean SHOW_INPUT_METHOD_SWITCHER_SETTINGS = false; + private static final String[] sSystemSettingNames = { + System.TEXT_AUTO_REPLACE, System.TEXT_AUTO_CAPS, System.TEXT_AUTO_PUNCTUATE, + }; + + private static final String[] sHardKeyboardKeys = { + "auto_replace", "auto_caps", "auto_punctuate", + }; private int mDefaultInputMethodSelectorVisibility = 0; private ListPreference mShowInputMethodSelectorPref; private Preference mLanguagePref; + private ArrayList<InputMethodPreference> mInputMethodPreferenceList = + new ArrayList<InputMethodPreference>(); + private boolean mHaveHardKeyboard; + private PreferenceCategory mHardKeyboardCategory; + private InputMethodManager mImm; + private List<InputMethodInfo> mImis; + private boolean mIsOnlyImeSettings; @Override public void onCreate(Bundle icicle) { @@ -66,13 +92,26 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment } else { mLanguagePref = findPreference(KEY_PHONE_LANGUAGE); } - mShowInputMethodSelectorPref = (ListPreference)findPreference( - KEY_INPUT_METHOD_SELECTOR); - mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); - // TODO: Update current input method name on summary - updateInputMethodSelectorSummary(loadInputMethodSelectorVisibility()); + if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { + mShowInputMethodSelectorPref = (ListPreference)findPreference( + KEY_INPUT_METHOD_SELECTOR); + mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); + // TODO: Update current input method name on summary + updateInputMethodSelectorSummary(loadInputMethodSelectorVisibility()); + } new VoiceInputOutputSettings(this).onCreate(); + + // Hard keyboard + final Configuration config = getResources().getConfiguration(); + mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY); + + // IME + mIsOnlyImeSettings = Settings.ACTION_INPUT_METHOD_SETTINGS.equals( + getActivity().getIntent().getAction()); + mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + mImis = mImm.getInputMethodList(); + createImePreferenceHierarchy((PreferenceGroup)findPreference("keyboard_settings_category")); } private void updateInputMethodSelectorSummary(int value) { @@ -109,23 +148,46 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment @Override public void onResume() { super.onResume(); - if (mLanguagePref != null) { - Configuration conf = getResources().getConfiguration(); - String locale = conf.locale.getDisplayName(conf.locale); - if (locale != null && locale.length() > 1) { - locale = Character.toUpperCase(locale.charAt(0)) + locale.substring(1); - mLanguagePref.setSummary(locale); + if (!mIsOnlyImeSettings) { + if (mLanguagePref != null) { + Configuration conf = getResources().getConfiguration(); + String locale = conf.locale.getDisplayName(conf.locale); + if (locale != null && locale.length() > 1) { + locale = Character.toUpperCase(locale.charAt(0)) + locale.substring(1); + mLanguagePref.setSummary(locale); + } + } + + updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS)); + if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { + mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); + } + } + + // Hard keyboard + if (mHaveHardKeyboard) { + for (int i = 0; i < sHardKeyboardKeys.length; ++i) { + InputMethodPreference chkPref = (InputMethodPreference) + mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i]); + chkPref.setChecked( + System.getInt(getContentResolver(), sSystemSettingNames[i], 1) > 0); } } - updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS)); - mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); + // IME + InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( + this, getContentResolver(), mImis, null); + updateActiveInputMethodsSummary(); } @Override public void onPause() { super.onPause(); - mShowInputMethodSelectorPref.setOnPreferenceChangeListener(null); + if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { + mShowInputMethodSelectorPref.setOnPreferenceChangeListener(null); + } + InputMethodAndSubtypeUtil.saveInputMethodSubtypeList( + this, getContentResolver(), mImis, mHaveHardKeyboard); } @Override @@ -142,6 +204,17 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment getSystemService(Context.INPUT_METHOD_SERVICE); imm.showInputMethodPicker(); } + } else if (preference instanceof CheckBoxPreference) { + final CheckBoxPreference chkPref = (CheckBoxPreference) preference; + if (mHaveHardKeyboard) { + for (int i = 0; i < sHardKeyboardKeys.length; ++i) { + if (chkPref == mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i])) { + System.putInt(getContentResolver(), sSystemSettingNames[i], + chkPref.isChecked() ? 1 : 0); + return true; + } + } + } } return super.onPreferenceTreeClick(preferenceScreen, preference); } @@ -164,12 +237,84 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment @Override public boolean onPreferenceChange(Preference preference, Object value) { - if (preference == mShowInputMethodSelectorPref) { - if (value instanceof String) { - saveInputMethodSelectorVisibility((String)value); + if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { + if (preference == mShowInputMethodSelectorPref) { + if (value instanceof String) { + saveInputMethodSelectorVisibility((String)value); + } } } return false; } + private void updateActiveInputMethodsSummary() { + for (Preference pref : mInputMethodPreferenceList) { + if (pref instanceof InputMethodPreference) { + ((InputMethodPreference)pref).updateSummary(); + } + } + } + + private InputMethodPreference getInputMethodPreference(InputMethodInfo imi, int imiSize) { + final PackageManager pm = getPackageManager(); + final CharSequence label = imi.loadLabel(pm); + // IME settings + final Intent intent; + final String settingsActivity = imi.getSettingsActivity(); + if (!TextUtils.isEmpty(settingsActivity)) { + intent = new Intent(Intent.ACTION_MAIN); + intent.setClassName(imi.getPackageName(), settingsActivity); + } else { + intent = null; + } + + // Add a check box for enabling/disabling IME + InputMethodPreference pref = new InputMethodPreference(this, intent, mImm, imi, imiSize); + pref.setKey(imi.getId()); + pref.setTitle(label); + return pref; + } + + private void createImePreferenceHierarchy(PreferenceGroup root) { + final Preference hardKeyPref = findPreference("hard_keyboard"); + if (mIsOnlyImeSettings) { + getPreferenceScreen().removeAll(); + if (hardKeyPref != null && mHaveHardKeyboard) { + getPreferenceScreen().addPreference(hardKeyPref); + } + if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { + getPreferenceScreen().addPreference(mShowInputMethodSelectorPref); + } + getPreferenceScreen().addPreference(root); + } + if (hardKeyPref != null) { + if (mHaveHardKeyboard) { + mHardKeyboardCategory = (PreferenceCategory) hardKeyPref; + } else { + getPreferenceScreen().removePreference(hardKeyPref); + } + } + root.removeAll(); + mInputMethodPreferenceList.clear(); + + if (!mIsOnlyImeSettings) { + // Current IME selection + final PreferenceScreen currentIme = new PreferenceScreen(getActivity(), null); + currentIme.setKey(KEY_CURRENT_INPUT_METHOD); + currentIme.setTitle(getResources().getString(R.string.current_input_method)); + root.addPreference(currentIme); + } + + final int N = (mImis == null ? 0 : mImis.size()); + for (int i = 0; i < N; ++i) { + final InputMethodInfo imi = mImis.get(i); + final InputMethodPreference pref = getInputMethodPreference(imi, N); + mInputMethodPreferenceList.add(pref); + } + + Collections.sort(mInputMethodPreferenceList); + for (int i = 0; i < N; ++i) { + root.addPreference(mInputMethodPreferenceList.get(i)); + } + } } diff --git a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java index 362fbb5..f62edc4 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java +++ b/src/com/android/settings/inputmethod/InputMethodAndSubtypeUtil.java @@ -169,9 +169,10 @@ public class InputMethodAndSubtypeUtil { 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) { + final boolean isCurrentInputMethod = imiId.equals(currentInputMethodId); + final boolean auxIme = isAuxiliaryIme(imi); + final boolean systemIme = isSystemIme(imi); + if (((onlyOneIME || (systemIme && !auxIme)) && !hasHardKeyboard) || isImeChecked) { if (!enabledIMEAndSubtypesMap.containsKey(imiId)) { // imiId has just been enabled enabledIMEAndSubtypesMap.put(imiId, new HashSet<String>()); @@ -276,7 +277,7 @@ public class InputMethodAndSubtypeUtil { List<InputMethodInfo> inputMethodInfos, final Map<String, List<Preference>> inputMethodPrefsMap) { HashMap<String, HashSet<String>> enabledSubtypes = - getEnabledInputMethodsAndSubtypeList(resolver); + getEnabledInputMethodsAndSubtypeList(resolver); for (InputMethodInfo imi : inputMethodInfos) { final String imiId = imi.getId(); @@ -342,4 +343,19 @@ public class InputMethodAndSubtypeUtil { return (property.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } + + public static boolean isAuxiliaryIme(InputMethodInfo imi) { + final int subtypeCount = imi.getSubtypeCount(); + if (subtypeCount == 0) { + return false; + } else { + for (int i = 0; i < subtypeCount; ++i) { + final InputMethodSubtype subtype = imi.getSubtypeAt(i); + if (!subtype.isAuxiliary()) { + return false; + } + } + } + return true; + } } diff --git a/src/com/android/settings/inputmethod/InputMethodConfig.java b/src/com/android/settings/inputmethod/InputMethodConfig.java deleted file mode 100644 index 393292e..0000000 --- a/src/com/android/settings/inputmethod/InputMethodConfig.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * 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.ContentResolver; -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.Preference.OnPreferenceClickListener; -import android.preference.PreferenceCategory; -import android.preference.PreferenceScreen; -import android.provider.Settings; -import android.provider.Settings.System; -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 InputMethodConfig extends SettingsPreferenceFragment { - - private static final String[] sSystemSettingNames = { - System.TEXT_AUTO_REPLACE, System.TEXT_AUTO_CAPS, System.TEXT_AUTO_PUNCTUATE, - }; - - private static final String[] sHardKeyboardKeys = { - "auto_replace", "auto_caps", "auto_punctuate", - }; - - private AlertDialog mDialog = null; - private boolean mHaveHardKeyboard; - private PreferenceCategory mHardKeyboardCategory; - // Map of imi and its preferences - final private HashMap<String, List<Preference>> mInputMethodPrefsMap = - new HashMap<String, List<Preference>>(); - final private HashMap<InputMethodInfo, Preference> mActiveInputMethodsPrefMap = - new HashMap<InputMethodInfo, 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(); - - ContentResolver resolver = getContentResolver(); - if (mHaveHardKeyboard) { - for (int i = 0; i < sHardKeyboardKeys.length; ++i) { - CheckBoxPreference chkPref = (CheckBoxPreference) - mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i]); - chkPref.setChecked(System.getInt(resolver, sSystemSettingNames[i], 1) > 0); - } - } - - InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( - this, resolver, mInputMethodProperties, mInputMethodPrefsMap); - updateActiveInputMethodsSummary(); - } - - @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.isShowing()) { - mDialog.dismiss(); - } - 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(); - 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; - - if (mHaveHardKeyboard) { - for (int i = 0; i < sHardKeyboardKeys.length; ++i) { - if (chkPref == mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i])) { - System.putInt(getContentResolver(), sSystemSettingNames[i], - chkPref.isChecked() ? 1 : 0); - return true; - } - } - } - - 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 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 (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.getSubtypeCount() > 1) { - prefScreen.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference){ - final Bundle bundle = new Bundle(); - bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId); - startFragment(InputMethodConfig.this, - InputMethodAndSubtypeEnabler.class.getName(), - 0, bundle); - return true; - } - }); - keyboardSettingsCategory.addPreference(prefScreen); - mActiveInputMethodsPrefMap.put(imi, 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() { - addPreferencesFromResource(R.xml.hard_keyboard_settings); - PreferenceScreen root = getPreferenceScreen(); - - if (mHaveHardKeyboard) { - mHardKeyboardCategory = (PreferenceCategory) findPreference("hard_keyboard"); - } else { - root.removeAll(); - } - - final int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size()); - for (int i = 0; i < N; ++i) { - addInputMethodPreference(root, mInputMethodProperties.get(i), N); - } - return root; - } - - private void updateActiveInputMethodsSummary() { - final InputMethodManager imm = - (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); - for (InputMethodInfo imi: mActiveInputMethodsPrefMap.keySet()) { - Preference pref = mActiveInputMethodsPrefMap.get(imi); - List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(imi, true); - StringBuilder summary = new StringBuilder(); - boolean subtypeAdded = false; - for (InputMethodSubtype subtype: subtypes) { - if (subtypeAdded) { - summary.append(", "); - } - final CharSequence subtypeLabel = subtype.getDisplayName(getActivity(), - imi.getPackageName(), imi.getServiceInfo().applicationInfo); - summary.append(subtypeLabel); - subtypeAdded = true; - } - pref.setSummary(summary.toString()); - } - } -} diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java new file mode 100644 index 0000000..21057a6 --- /dev/null +++ b/src/com/android/settings/inputmethod/InputMethodPreference.java @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2011 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.app.Fragment; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.PreferenceActivity; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; +import android.view.inputmethod.InputMethodSubtype; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.Comparator; +import java.util.List; + +public class InputMethodPreference extends CheckBoxPreference + implements Comparator<InputMethodPreference> { + private static final String TAG = InputMethodPreference.class.getSimpleName(); + private static final float DISABLED_ALPHA = 0.4f; + private final SettingsPreferenceFragment mFragment; + private final InputMethodInfo mImi; + private final InputMethodManager mImm; + private final Intent mSettingsIntent; + private final boolean mIsSystemIme; + + private AlertDialog mDialog = null; + private ImageView mInputMethodSettingsButton; + private TextView mTitleText; + private TextView mSummaryText; + private View mInputMethodPref; + + public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent, + InputMethodManager imm, InputMethodInfo imi, int imiCount) { + super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle); + setLayoutResource(R.layout.preference_inputmethod); + setWidgetLayoutResource(R.layout.preference_inputmethod_widget); + mFragment = fragment; + mSettingsIntent = settingsIntent; + mImm = imm; + mImi = imi; + updateSummary(); + mIsSystemIme = InputMethodAndSubtypeUtil.isSystemIme(imi); + final boolean isAuxIme = InputMethodAndSubtypeUtil.isAuxiliaryIme(imi); + if (imiCount <= 1 || (mIsSystemIme && !isAuxIme)) { + setEnabled(false); + } + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + mInputMethodPref = view.findViewById(R.id.inputmethod_pref); + mInputMethodPref.setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View arg0) { + if (isChecked()) { + setChecked(false); + } else { + if (mIsSystemIme) { + setChecked(true); + } else { + showSecurityWarnDialog(mImi, InputMethodPreference.this); + } + } + } + }); + mInputMethodSettingsButton = (ImageView)view.findViewById(R.id.inputmethod_settings); + mTitleText = (TextView)view.findViewById(android.R.id.title); + mSummaryText = (TextView)view.findViewById(android.R.id.summary); + if (mSettingsIntent != null) { + mInputMethodSettingsButton.setOnClickListener( + new OnClickListener() { + @Override + public void onClick(View arg0) { + mFragment.startActivity(mSettingsIntent); + } + }); + } + final boolean hasSubtypes = mImi.getSubtypeCount() > 1; + final String imiId = mImi.getId(); + if (hasSubtypes) { + final OnLongClickListener listener = new OnLongClickListener() { + @Override + public boolean onLongClick(View arg0) { + final Bundle bundle = new Bundle(); + bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId); + startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(), + 0, bundle); + return true; + } + }; + mInputMethodSettingsButton.setOnLongClickListener(listener); + } + if (mSettingsIntent == null) { + mInputMethodSettingsButton.setVisibility(View.GONE); + } else { + enableSettingsButton(); + } + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + enableSettingsButton(); + } + + private void enableSettingsButton() { + if (mInputMethodSettingsButton != null) { + final boolean checked = isChecked(); + mInputMethodSettingsButton.setEnabled(checked); + mInputMethodSettingsButton.setClickable(checked); + mInputMethodSettingsButton.setFocusable(checked); + if (!checked) { + mInputMethodSettingsButton.setAlpha(DISABLED_ALPHA); + } + } + if (mTitleText != null) { + mTitleText.setEnabled(true); + } + if (mSummaryText != null) { + mSummaryText.setEnabled(true); + } + } + + public static boolean startFragment( + Fragment fragment, String fragmentClass, int requestCode, Bundle extras) { + if (fragment.getActivity() instanceof PreferenceActivity) { + PreferenceActivity preferenceActivity = (PreferenceActivity)fragment.getActivity(); + preferenceActivity.startPreferencePanel(fragmentClass, extras, 0, null, fragment, + requestCode); + return true; + } else { + Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the " + + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode + + ")"); + return false; + } + } + + public String getSummaryString() { + final StringBuilder builder = new StringBuilder(); + final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true); + for (InputMethodSubtype subtype : subtypes) { + if (builder.length() > 0) { + builder.append(", "); + } + final CharSequence subtypeLabel = subtype.getDisplayName(mFragment.getActivity(), + mImi.getPackageName(), mImi.getServiceInfo().applicationInfo); + builder.append(subtypeLabel); + } + return builder.toString(); + } + + public void updateSummary() { + final String summary = getSummaryString(); + if (TextUtils.isEmpty(summary)) { + return; + } + setSummary(summary); + } + + @Override + public void setChecked(boolean checked) { + super.setChecked(checked); + saveImeSettings(); + } + + private void showSecurityWarnDialog(InputMethodInfo imi, final CheckBoxPreference chkPref) { + if (mDialog != null && mDialog.isShowing()) { + mDialog.dismiss(); + } + mDialog = (new AlertDialog.Builder(mFragment.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() { + @Override + public void onClick(DialogInterface dialog, int which) { + chkPref.setChecked(true); + } + }) + .setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }) + .create(); + mDialog.setMessage(mFragment.getResources().getString(R.string.ime_security_warning, + imi.getServiceInfo().applicationInfo.loadLabel( + mFragment.getActivity().getPackageManager()))); + mDialog.show(); + } + + @Override + public int compare(InputMethodPreference arg0, InputMethodPreference arg1) { + if (arg0.isEnabled() == arg0.isEnabled()) { + return arg0.mImi.getId().compareTo(arg1.mImi.getId()); + } else { + // Prefer system IMEs + return arg0.isEnabled() ? 1 : -1; + } + } + + private void saveImeSettings() { + InputMethodAndSubtypeUtil.saveInputMethodSubtypeList( + mFragment, mFragment.getActivity().getContentResolver(), mImm.getInputMethodList(), + mFragment.getResources().getConfiguration().keyboard + == Configuration.KEYBOARD_QWERTY); + } +} |