14a5f889f80b683446e498f244d0eadfd979ca5d0satok/* 24a5f889f80b683446e498f244d0eadfd979ca5d0satok * Copyright (C) 2010 The Android Open Source Project 34a5f889f80b683446e498f244d0eadfd979ca5d0satok * 44a5f889f80b683446e498f244d0eadfd979ca5d0satok * Licensed under the Apache License, Version 2.0 (the "License"); 54a5f889f80b683446e498f244d0eadfd979ca5d0satok * you may not use this file except in compliance with the License. 64a5f889f80b683446e498f244d0eadfd979ca5d0satok * You may obtain a copy of the License at 74a5f889f80b683446e498f244d0eadfd979ca5d0satok * 84a5f889f80b683446e498f244d0eadfd979ca5d0satok * http://www.apache.org/licenses/LICENSE-2.0 94a5f889f80b683446e498f244d0eadfd979ca5d0satok * 104a5f889f80b683446e498f244d0eadfd979ca5d0satok * Unless required by applicable law or agreed to in writing, software 114a5f889f80b683446e498f244d0eadfd979ca5d0satok * distributed under the License is distributed on an "AS IS" BASIS, 124a5f889f80b683446e498f244d0eadfd979ca5d0satok * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134a5f889f80b683446e498f244d0eadfd979ca5d0satok * See the License for the specific language governing permissions and 144a5f889f80b683446e498f244d0eadfd979ca5d0satok * limitations under the License. 154a5f889f80b683446e498f244d0eadfd979ca5d0satok */ 164a5f889f80b683446e498f244d0eadfd979ca5d0satok 170417e4094713c5f4dac700b645000d0959bf62fasatokpackage com.android.settings.inputmethod; 180417e4094713c5f4dac700b645000d0959bf62fasatok 194a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.Context; 205e9c5e7bcfbdc3d61f80bc95d16a7d57a362bc39satokimport android.content.Intent; 214a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.pm.PackageManager; 224a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.res.Configuration; 234a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.os.Bundle; 244a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.Preference; 255d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaokaimport android.preference.Preference.OnPreferenceChangeListener; 264a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceCategory; 274a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceScreen; 281f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaokaimport android.preference.TwoStatePreference; 29c88a7ff1efd10374974e45768bde1658cc1d8483satokimport android.text.TextUtils; 304a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodInfo; 314a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodManager; 324a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodSubtype; 334a5f889f80b683446e498f244d0eadfd979ca5d0satok 3455aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaokaimport com.android.settings.R; 3555aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaokaimport com.android.settings.SettingsPreferenceFragment; 3655aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaoka 37ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataokaimport java.text.Collator; 384a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.ArrayList; 39ae70ee49492bd89c949946562b43a75f3c81b0adsatokimport java.util.Collections; 4055aee124063dc28e740efcfdadafa5738b0b538aTadashi G. Takaokaimport java.util.Comparator; 41c88a7ff1efd10374974e45768bde1658cc1d8483satokimport java.util.HashMap; 424a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.List; 434a5f889f80b683446e498f244d0eadfd979ca5d0satok 445d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaokapublic class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment 455d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka implements OnPreferenceChangeListener { 46c88a7ff1efd10374974e45768bde1658cc1d8483satok private boolean mHaveHardKeyboard; 47989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private final HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap = 48d2dd7d33c9206f7aa29abbff48119d0f86ddfc36Tadashi G. Takaoka new HashMap<>(); 491f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka private final HashMap<String, TwoStatePreference> mAutoSelectionPrefsMap = new HashMap<>(); 501c58c15e7a84b582b7d4d20c26824cabce80bce9satok private InputMethodManager mImm; 5172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka // TODO: Change mInputMethodInfoList to Map 5272c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka private List<InputMethodInfo> mInputMethodInfoList; 53989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private Collator mCollator; 544a5f889f80b683446e498f244d0eadfd979ca5d0satok 554a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 5672c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka public void onCreate(final Bundle icicle) { 574a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onCreate(icicle); 581c58c15e7a84b582b7d4d20c26824cabce80bce9satok mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 59ae70ee49492bd89c949946562b43a75f3c81b0adsatok final Configuration config = getResources().getConfiguration(); 604a5f889f80b683446e498f244d0eadfd979ca5d0satok mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY); 61649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa 62649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // Input method id should be available from an Intent when this preference is launched as a 63649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // single Activity (see InputMethodAndSubtypeEnablerActivity). It should be available 64649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // from a preference argument when the preference is launched as a part of the other 65649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // Activity (like a right pane of 2-pane Settings app) 66fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String targetImi = getStringExtraFromIntentOrArguments( 679f7320132b7a5e7def378ae754c8c708759a8670Tadashi G. Takaoka android.provider.Settings.EXTRA_INPUT_METHOD_ID); 68649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa 6972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka mInputMethodInfoList = mImm.getInputMethodList(); 70989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka mCollator = Collator.getInstance(); 71fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka 72fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity()); 73fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final int imiCount = mInputMethodInfoList.size(); 74fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (int index = 0; index < imiCount; ++index) { 75fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final InputMethodInfo imi = mInputMethodInfoList.get(index); 76fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // Add subtype preferences of this IME when it is specified or no IME is specified. 77fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (imi.getId().equals(targetImi) || TextUtils.isEmpty(targetImi)) { 78fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka addInputMethodSubtypePreferences(imi, root); 79fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 80fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 81fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka setPreferenceScreen(root); 824a5f889f80b683446e498f244d0eadfd979ca5d0satok } 834a5f889f80b683446e498f244d0eadfd979ca5d0satok 8472c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka private String getStringExtraFromIntentOrArguments(final String name) { 8572c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final Intent intent = getActivity().getIntent(); 8672c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final String fromIntent = intent.getStringExtra(name); 8772c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka if (fromIntent != null) { 8872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka return fromIntent; 8972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 9072c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final Bundle arguments = getArguments(); 9172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka return (arguments == null) ? null : arguments.getString(name); 9272c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 9372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka 944a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 9572c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka public void onActivityCreated(final Bundle icicle) { 9616c3e74d72ec2d18aff007cb88fcf02995918a90satok super.onActivityCreated(icicle); 9772c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final String title = getStringExtraFromIntentOrArguments(Intent.EXTRA_TITLE); 9872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka if (!TextUtils.isEmpty(title)) { 9972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka getActivity().setTitle(title); 10016c3e74d72ec2d18aff007cb88fcf02995918a90satok } 10116c3e74d72ec2d18aff007cb88fcf02995918a90satok } 10216c3e74d72ec2d18aff007cb88fcf02995918a90satok 10316c3e74d72ec2d18aff007cb88fcf02995918a90satok @Override 1044a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onResume() { 1054a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onResume(); 106cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka // Refresh internal states in mInputMethodSettingValues to keep the latest 107cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka // "InputMethodInfo"s and "InputMethodSubtype"s 108cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka InputMethodSettingValuesWrapper 109cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka .getInstance(getActivity()).refreshAllInputMethodAndSubtypes(); 1100417e4094713c5f4dac700b645000d0959bf62fasatok InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( 11172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka this, getContentResolver(), mInputMethodInfoList, mInputMethodAndSubtypePrefsMap); 112989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka updateAutoSelectionPreferences(); 1134a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1144a5f889f80b683446e498f244d0eadfd979ca5d0satok 1154a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 1164a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onPause() { 1174a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onPause(); 1181c58c15e7a84b582b7d4d20c26824cabce80bce9satok // Clear all subtypes of all IMEs to make sure 119989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka updateImplicitlyEnabledSubtypes(null /* targetImiId */, false /* check */); 1200417e4094713c5f4dac700b645000d0959bf62fasatok InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(), 12172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka mInputMethodInfoList, mHaveHardKeyboard); 1224a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1234a5f889f80b683446e498f244d0eadfd979ca5d0satok 1244a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 1255d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka public boolean onPreferenceChange(final Preference pref, final Object newValue) { 1265d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka if (!(newValue instanceof Boolean)) { 1275d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka return true; // Invoke default behavior. 128fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 1295d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka final boolean isChecking = (Boolean) newValue; 130fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (final String imiId : mAutoSelectionPrefsMap.keySet()) { 1315d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka // An auto select subtype preference is changing. 1325d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka if (mAutoSelectionPrefsMap.get(imiId) == pref) { 1331f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka final TwoStatePreference autoSelectionPref = (TwoStatePreference) pref; 1345d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka autoSelectionPref.setChecked(isChecking); 1355d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka // Enable or disable subtypes depending on the auto selection preference. 1365d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka setAutoSelectionSubtypesEnabled(imiId, autoSelectionPref.isChecked()); 1375d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka return false; 1381c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 139fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 1405d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka // A subtype preference is changing. 1415d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka if (pref instanceof InputMethodSubtypePreference) { 1425d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka final InputMethodSubtypePreference subtypePref = (InputMethodSubtypePreference) pref; 1435d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka subtypePref.setChecked(isChecking); 1445d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka if (!subtypePref.isChecked()) { 1455d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka // It takes care of the case where no subtypes are explicitly enabled then the auto 1465d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka // selection preference is going to be checked. 1475d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka updateAutoSelectionPreferences(); 1485d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka } 1495d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka return false; 150fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 1515d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka return true; // Invoke default behavior. 1524a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1534a5f889f80b683446e498f244d0eadfd979ca5d0satok 154fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka private void addInputMethodSubtypePreferences(final InputMethodInfo imi, 155fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PreferenceScreen root) { 156f0ae329740eb66663b6f099ca24a13ea7572418csatok final Context context = getActivity(); 157fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final int subtypeCount = imi.getSubtypeCount(); 158fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (subtypeCount <= 1) { 159fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return; 160fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 161fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String imiId = imi.getId(); 162fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(context); 163fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka root.addPreference(keyboardSettingsCategory); 164fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PackageManager pm = getPackageManager(); 165fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final CharSequence label = imi.loadLabel(pm); 1664a5f889f80b683446e498f244d0eadfd979ca5d0satok 167fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka keyboardSettingsCategory.setTitle(label); 168fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka keyboardSettingsCategory.setKey(imiId); 169fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka // TODO: Use toggle Preference if images are ready. 1701f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka final TwoStatePreference autoSelectionPref = new SwitchWithNoTextPreference(context); 171fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mAutoSelectionPrefsMap.put(imiId, autoSelectionPref); 172fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka keyboardSettingsCategory.addPreference(autoSelectionPref); 1735d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka autoSelectionPref.setOnPreferenceChangeListener(this); 1741c58c15e7a84b582b7d4d20c26824cabce80bce9satok 175fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final PreferenceCategory activeInputMethodsCategory = new PreferenceCategory(context); 176fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes); 177fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka root.addPreference(activeInputMethodsCategory); 1784a5f889f80b683446e498f244d0eadfd979ca5d0satok 179fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka CharSequence autoSubtypeLabel = null; 180fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final ArrayList<Preference> subtypePreferences = new ArrayList<>(); 181fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (int index = 0; index < subtypeCount; ++index) { 182fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final InputMethodSubtype subtype = imi.getSubtypeAt(index); 183fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (subtype.overridesImplicitlyEnabledSubtype()) { 184fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (autoSubtypeLabel == null) { 185fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka autoSubtypeLabel = subtype.getDisplayName( 186fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka context, imi.getPackageName(), imi.getServiceInfo().applicationInfo); 1874a5f889f80b683446e498f244d0eadfd979ca5d0satok } 188fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } else { 189fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final Preference subtypePref = new InputMethodSubtypePreference( 190fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka context, subtype, imi); 191fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka subtypePreferences.add(subtypePref); 192989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka } 193fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 194fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka Collections.sort(subtypePreferences, new Comparator<Preference>() { 195fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka @Override 196fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka public int compare(final Preference lhs, final Preference rhs) { 197fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (lhs instanceof InputMethodSubtypePreference) { 198fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return ((InputMethodSubtypePreference) lhs).compareTo(rhs, mCollator); 199ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 200fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return lhs.compareTo(rhs); 20194bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } 202fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka }); 203fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final int prefCount = subtypePreferences.size(); 204fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (int index = 0; index < prefCount; ++index) { 205fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final Preference pref = subtypePreferences.get(index); 206fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka activeInputMethodsCategory.addPreference(pref); 2075d56f6217f237ec6f1dc20a1c9f7886ca3c6a717Tadashi G. Takaoka pref.setOnPreferenceChangeListener(this); 2083460a2683ca820d8d7d184bc1e98241ea3986a4aTadashi G. Takaoka InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref); 209fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 210fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences); 211fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (TextUtils.isEmpty(autoSubtypeLabel)) { 212fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka autoSelectionPref.setTitle( 213fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka R.string.use_system_language_to_select_input_method_subtypes); 214fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } else { 215fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka autoSelectionPref.setTitle(autoSubtypeLabel); 2164a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2174a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2181c58c15e7a84b582b7d4d20c26824cabce80bce9satok 219989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private boolean isNoSubtypesExplicitlySelected(final String imiId) { 2201c58c15e7a84b582b7d4d20c26824cabce80bce9satok final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 22172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka for (final Preference pref : subtypePrefs) { 2221f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka if (pref instanceof TwoStatePreference && ((TwoStatePreference)pref).isChecked()) { 223989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka return false; 2241c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2251c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 226989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka return true; 2271c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2281c58c15e7a84b582b7d4d20c26824cabce80bce9satok 229989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private void setAutoSelectionSubtypesEnabled(final String imiId, 230989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka final boolean autoSelectionEnabled) { 2311f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId); 232989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka if (autoSelectionPref == null) { 23372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka return; 23472c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 235989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka autoSelectionPref.setChecked(autoSelectionEnabled); 2361c58c15e7a84b582b7d4d20c26824cabce80bce9satok final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 237989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka for (final Preference pref : subtypePrefs) { 2381f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka if (pref instanceof TwoStatePreference) { 2391c58c15e7a84b582b7d4d20c26824cabce80bce9satok // When autoSelectionEnabled is true, all subtype prefs need to be disabled with 2401c58c15e7a84b582b7d4d20c26824cabce80bce9satok // implicitly checked subtypes. In case of false, all subtype prefs need to be 2411c58c15e7a84b582b7d4d20c26824cabce80bce9satok // enabled. 242989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka pref.setEnabled(!autoSelectionEnabled); 2431c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (autoSelectionEnabled) { 2441f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka ((TwoStatePreference)pref).setChecked(false); 2451c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2461c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2471c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2481c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (autoSelectionEnabled) { 24972c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka InputMethodAndSubtypeUtil.saveInputMethodSubtypeList( 25072c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka this, getContentResolver(), mInputMethodInfoList, mHaveHardKeyboard); 251989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka updateImplicitlyEnabledSubtypes(imiId, true /* check */); 2521c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2531c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2541c58c15e7a84b582b7d4d20c26824cabce80bce9satok 255989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private void updateImplicitlyEnabledSubtypes(final String targetImiId, final boolean check) { 2561c58c15e7a84b582b7d4d20c26824cabce80bce9satok // When targetImiId is null, apply to all subtypes of all IMEs 25772c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka for (final InputMethodInfo imi : mInputMethodInfoList) { 25872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka final String imiId = imi.getId(); 2591f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka final TwoStatePreference autoSelectionPref = mAutoSelectionPrefsMap.get(imiId); 2601c58c15e7a84b582b7d4d20c26824cabce80bce9satok // No need to update implicitly enabled subtypes when the user has unchecked the 2611c58c15e7a84b582b7d4d20c26824cabce80bce9satok // "subtype auto selection". 262989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka if (autoSelectionPref == null || !autoSelectionPref.isChecked()) { 26372c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka continue; 26472c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 265fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (imiId.equals(targetImiId) || targetImiId == null) { 266fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka updateImplicitlyEnabledSubtypesOf(imi, check); 267fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 268fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 269fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 270fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka 271fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka private void updateImplicitlyEnabledSubtypesOf(final InputMethodInfo imi, final boolean check) { 272fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String imiId = imi.getId(); 273fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 274fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final List<InputMethodSubtype> implicitlyEnabledSubtypes = 275fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka mImm.getEnabledInputMethodSubtypeList(imi, true); 276fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (subtypePrefs == null || implicitlyEnabledSubtypes == null) { 277fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka return; 278fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka } 279fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (final Preference pref : subtypePrefs) { 2801f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka if (!(pref instanceof TwoStatePreference)) { 28172c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka continue; 28272c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka } 2831f53937469095f268d4c7a21d93f821a341a151dTadashi G. Takaoka final TwoStatePreference subtypePref = (TwoStatePreference)pref; 284fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka subtypePref.setChecked(false); 285fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (check) { 286fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka for (final InputMethodSubtype subtype : implicitlyEnabledSubtypes) { 287fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka final String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode(); 288fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka if (subtypePref.getKey().equals(implicitlyEnabledSubtypePrefKey)) { 289fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka subtypePref.setChecked(true); 290fc8202463e64d9e85af3c99c1d8552d4bb74b7dcTadashi G. Takaoka break; 2911c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2921c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2931c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2941c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2951c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 2961c58c15e7a84b582b7d4d20c26824cabce80bce9satok 297989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka private void updateAutoSelectionPreferences() { 29872c2a6e5c2990df7f36c4f7305d4ba4b28e10023Tadashi G. Takaoka for (final String imiId : mInputMethodAndSubtypePrefsMap.keySet()) { 299989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka setAutoSelectionSubtypesEnabled(imiId, isNoSubtypesExplicitlySelected(imiId)); 3001c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 301989c364f2de3eeb2c92fa6713b8e0f137e8d971aTadashi G. Takaoka updateImplicitlyEnabledSubtypes(null /* targetImiId */, true /* check */); 3021c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3034a5f889f80b683446e498f244d0eadfd979ca5d0satok} 304