InputMethodAndSubtypeEnabler.java revision cabde98bcddc2c609a5929b019ebe73f1a68e004
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 19993f6ecf4065501433271b5fd5daf21a6f3ae586Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils; 200417e4094713c5f4dac700b645000d0959bf62fasatokimport com.android.settings.R; 210417e4094713c5f4dac700b645000d0959bf62fasatokimport com.android.settings.SettingsPreferenceFragment; 224a5f889f80b683446e498f244d0eadfd979ca5d0satok 234a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.app.AlertDialog; 244a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.Context; 254a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.DialogInterface; 265e9c5e7bcfbdc3d61f80bc95d16a7d57a362bc39satokimport android.content.Intent; 274a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.pm.PackageManager; 284a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.content.res.Configuration; 294a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.os.Bundle; 304a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.CheckBoxPreference; 314a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.Preference; 324a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceCategory; 334a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.preference.PreferenceScreen; 34c88a7ff1efd10374974e45768bde1658cc1d8483satokimport android.text.TextUtils; 3594bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatokimport android.util.Log; 364a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodInfo; 374a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodManager; 384a5f889f80b683446e498f244d0eadfd979ca5d0satokimport android.view.inputmethod.InputMethodSubtype; 394a5f889f80b683446e498f244d0eadfd979ca5d0satok 40ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataokaimport java.text.Collator; 414a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.ArrayList; 42ae70ee49492bd89c949946562b43a75f3c81b0adsatokimport java.util.Collections; 43ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataokaimport java.util.Comparator; 44c88a7ff1efd10374974e45768bde1658cc1d8483satokimport java.util.HashMap; 454a5f889f80b683446e498f244d0eadfd979ca5d0satokimport java.util.List; 46ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataokaimport java.util.Locale; 474a5f889f80b683446e498f244d0eadfd979ca5d0satok 484a5f889f80b683446e498f244d0eadfd979ca5d0satokpublic class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment { 4994bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok private static final String TAG =InputMethodAndSubtypeEnabler.class.getSimpleName(); 504a5f889f80b683446e498f244d0eadfd979ca5d0satok private AlertDialog mDialog = null; 51c88a7ff1efd10374974e45768bde1658cc1d8483satok private boolean mHaveHardKeyboard; 521c58c15e7a84b582b7d4d20c26824cabce80bce9satok final private HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap = 531c58c15e7a84b582b7d4d20c26824cabce80bce9satok new HashMap<String, List<Preference>>(); 541c58c15e7a84b582b7d4d20c26824cabce80bce9satok final private HashMap<String, CheckBoxPreference> mSubtypeAutoSelectionCBMap = 551c58c15e7a84b582b7d4d20c26824cabce80bce9satok new HashMap<String, CheckBoxPreference>(); 561c58c15e7a84b582b7d4d20c26824cabce80bce9satok private InputMethodManager mImm; 57c88a7ff1efd10374974e45768bde1658cc1d8483satok private List<InputMethodInfo> mInputMethodProperties; 58c88a7ff1efd10374974e45768bde1658cc1d8483satok private String mInputMethodId; 5916c3e74d72ec2d18aff007cb88fcf02995918a90satok private String mTitle; 60ae70ee49492bd89c949946562b43a75f3c81b0adsatok private String mSystemLocale = ""; 61ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka private Collator mCollator = Collator.getInstance(); 624a5f889f80b683446e498f244d0eadfd979ca5d0satok 634a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 644a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onCreate(Bundle icicle) { 654a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onCreate(icicle); 661c58c15e7a84b582b7d4d20c26824cabce80bce9satok mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 67ae70ee49492bd89c949946562b43a75f3c81b0adsatok final Configuration config = getResources().getConfiguration(); 684a5f889f80b683446e498f244d0eadfd979ca5d0satok mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY); 69649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa 705e9c5e7bcfbdc3d61f80bc95d16a7d57a362bc39satok final Bundle arguments = getArguments(); 71649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // Input method id should be available from an Intent when this preference is launched as a 72649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // single Activity (see InputMethodAndSubtypeEnablerActivity). It should be available 73649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // from a preference argument when the preference is launched as a part of the other 74649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa // Activity (like a right pane of 2-pane Settings app) 759f7320132b7a5e7def378ae754c8c708759a8670Tadashi G. Takaoka mInputMethodId = getActivity().getIntent().getStringExtra( 769f7320132b7a5e7def378ae754c8c708759a8670Tadashi G. Takaoka android.provider.Settings.EXTRA_INPUT_METHOD_ID); 775e9c5e7bcfbdc3d61f80bc95d16a7d57a362bc39satok if (mInputMethodId == null && (arguments != null)) { 78649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa final String inputMethodId = 795e9c5e7bcfbdc3d61f80bc95d16a7d57a362bc39satok arguments.getString(android.provider.Settings.EXTRA_INPUT_METHOD_ID); 80649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa if (inputMethodId != null) { 81649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa mInputMethodId = inputMethodId; 82649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa } 83649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa } 8416c3e74d72ec2d18aff007cb88fcf02995918a90satok mTitle = getActivity().getIntent().getStringExtra(Intent.EXTRA_TITLE); 8516c3e74d72ec2d18aff007cb88fcf02995918a90satok if (mTitle == null && (arguments != null)) { 8616c3e74d72ec2d18aff007cb88fcf02995918a90satok final String title = arguments.getString(Intent.EXTRA_TITLE); 8716c3e74d72ec2d18aff007cb88fcf02995918a90satok if (title != null) { 8816c3e74d72ec2d18aff007cb88fcf02995918a90satok mTitle = title; 8916c3e74d72ec2d18aff007cb88fcf02995918a90satok } 905e9c5e7bcfbdc3d61f80bc95d16a7d57a362bc39satok } 91649b9f19e1193547f339239afa32d569f43358fcDaisuke Miyakawa 92ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka final Locale locale = config.locale; 93ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka mSystemLocale = locale.toString(); 94ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka mCollator = Collator.getInstance(locale); 954a5f889f80b683446e498f244d0eadfd979ca5d0satok onCreateIMM(); 964a5f889f80b683446e498f244d0eadfd979ca5d0satok setPreferenceScreen(createPreferenceHierarchy()); 974a5f889f80b683446e498f244d0eadfd979ca5d0satok } 984a5f889f80b683446e498f244d0eadfd979ca5d0satok 994a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 10016c3e74d72ec2d18aff007cb88fcf02995918a90satok public void onActivityCreated(Bundle icicle) { 10116c3e74d72ec2d18aff007cb88fcf02995918a90satok super.onActivityCreated(icicle); 10216c3e74d72ec2d18aff007cb88fcf02995918a90satok if (!TextUtils.isEmpty(mTitle)) { 10316c3e74d72ec2d18aff007cb88fcf02995918a90satok getActivity().setTitle(mTitle); 10416c3e74d72ec2d18aff007cb88fcf02995918a90satok } 10516c3e74d72ec2d18aff007cb88fcf02995918a90satok } 10616c3e74d72ec2d18aff007cb88fcf02995918a90satok 10716c3e74d72ec2d18aff007cb88fcf02995918a90satok @Override 1084a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onResume() { 1094a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onResume(); 110cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka // Refresh internal states in mInputMethodSettingValues to keep the latest 111cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka // "InputMethodInfo"s and "InputMethodSubtype"s 112cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka InputMethodSettingValuesWrapper 113cabde98bcddc2c609a5929b019ebe73f1a68e004Satoshi Kataoka .getInstance(getActivity()).refreshAllInputMethodAndSubtypes(); 1140417e4094713c5f4dac700b645000d0959bf62fasatok InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( 1151c58c15e7a84b582b7d4d20c26824cabce80bce9satok this, getContentResolver(), mInputMethodProperties, mInputMethodAndSubtypePrefsMap); 1161c58c15e7a84b582b7d4d20c26824cabce80bce9satok updateAutoSelectionCB(); 1174a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1184a5f889f80b683446e498f244d0eadfd979ca5d0satok 1194a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 1204a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onPause() { 1214a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onPause(); 1221c58c15e7a84b582b7d4d20c26824cabce80bce9satok // Clear all subtypes of all IMEs to make sure 1231c58c15e7a84b582b7d4d20c26824cabce80bce9satok clearImplicitlyEnabledSubtypes(null); 1240417e4094713c5f4dac700b645000d0959bf62fasatok InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(), 1255fd39cafe1de792300e9e3dd60258a1ce5079f73satok mInputMethodProperties, mHaveHardKeyboard); 1264a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1274a5f889f80b683446e498f244d0eadfd979ca5d0satok 1284a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 1294a5f889f80b683446e498f244d0eadfd979ca5d0satok public boolean onPreferenceTreeClick( 1304a5f889f80b683446e498f244d0eadfd979ca5d0satok PreferenceScreen preferenceScreen, Preference preference) { 1314a5f889f80b683446e498f244d0eadfd979ca5d0satok 1324a5f889f80b683446e498f244d0eadfd979ca5d0satok if (preference instanceof CheckBoxPreference) { 1334a5f889f80b683446e498f244d0eadfd979ca5d0satok final CheckBoxPreference chkPref = (CheckBoxPreference) preference; 1341c58c15e7a84b582b7d4d20c26824cabce80bce9satok 1351c58c15e7a84b582b7d4d20c26824cabce80bce9satok for (String imiId: mSubtypeAutoSelectionCBMap.keySet()) { 1361c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (mSubtypeAutoSelectionCBMap.get(imiId) == chkPref) { 1371c58c15e7a84b582b7d4d20c26824cabce80bce9satok // We look for the first preference item in subtype enabler. 1381c58c15e7a84b582b7d4d20c26824cabce80bce9satok // The first item is used for turning on/off subtype auto selection. 1391c58c15e7a84b582b7d4d20c26824cabce80bce9satok // We are in the subtype enabler and trying selecting subtypes automatically. 1401c58c15e7a84b582b7d4d20c26824cabce80bce9satok setSubtypeAutoSelectionEnabled(imiId, chkPref.isChecked()); 1411c58c15e7a84b582b7d4d20c26824cabce80bce9satok return super.onPreferenceTreeClick(preferenceScreen, preference); 1421c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 1431c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 1441c58c15e7a84b582b7d4d20c26824cabce80bce9satok 1454a5f889f80b683446e498f244d0eadfd979ca5d0satok final String id = chkPref.getKey(); 1464a5f889f80b683446e498f244d0eadfd979ca5d0satok if (chkPref.isChecked()) { 1474a5f889f80b683446e498f244d0eadfd979ca5d0satok InputMethodInfo selImi = null; 1484a5f889f80b683446e498f244d0eadfd979ca5d0satok final int N = mInputMethodProperties.size(); 1494a5f889f80b683446e498f244d0eadfd979ca5d0satok for (int i = 0; i < N; i++) { 1504a5f889f80b683446e498f244d0eadfd979ca5d0satok InputMethodInfo imi = mInputMethodProperties.get(i); 1514a5f889f80b683446e498f244d0eadfd979ca5d0satok if (id.equals(imi.getId())) { 1524a5f889f80b683446e498f244d0eadfd979ca5d0satok selImi = imi; 153993f6ecf4065501433271b5fd5daf21a6f3ae586Satoshi Kataoka if (InputMethodUtils.isSystemIme(imi)) { 1549cd11a9aa5ac74ca89432655d019f68d789bc405satok InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled( 1559cd11a9aa5ac74ca89432655d019f68d789bc405satok this, mInputMethodProperties, id, true); 1564a5f889f80b683446e498f244d0eadfd979ca5d0satok // This is a built-in IME, so no need to warn. 1574a5f889f80b683446e498f244d0eadfd979ca5d0satok return super.onPreferenceTreeClick(preferenceScreen, preference); 1584a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1594a5f889f80b683446e498f244d0eadfd979ca5d0satok break; 1604a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1614a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1624a5f889f80b683446e498f244d0eadfd979ca5d0satok if (selImi == null) { 1634a5f889f80b683446e498f244d0eadfd979ca5d0satok return super.onPreferenceTreeClick(preferenceScreen, preference); 1644a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1654a5f889f80b683446e498f244d0eadfd979ca5d0satok chkPref.setChecked(false); 1664a5f889f80b683446e498f244d0eadfd979ca5d0satok if (mDialog == null) { 1674a5f889f80b683446e498f244d0eadfd979ca5d0satok mDialog = (new AlertDialog.Builder(getActivity())) 1684a5f889f80b683446e498f244d0eadfd979ca5d0satok .setTitle(android.R.string.dialog_alert_title) 169c8272b075275f81ddfb9cef2f92514b7ce3365deBjörn Lundén .setIconAttribute(android.R.attr.alertDialogIcon) 1704a5f889f80b683446e498f244d0eadfd979ca5d0satok .setCancelable(true) 1714a5f889f80b683446e498f244d0eadfd979ca5d0satok .setPositiveButton(android.R.string.ok, 1724a5f889f80b683446e498f244d0eadfd979ca5d0satok new DialogInterface.OnClickListener() { 173e077d2b607032fb66a4a046aa4b46945d32d281esatok @Override 1744a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onClick(DialogInterface dialog, int which) { 1754a5f889f80b683446e498f244d0eadfd979ca5d0satok chkPref.setChecked(true); 1769cd11a9aa5ac74ca89432655d019f68d789bc405satok InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled( 1779cd11a9aa5ac74ca89432655d019f68d789bc405satok InputMethodAndSubtypeEnabler.this, 1789cd11a9aa5ac74ca89432655d019f68d789bc405satok mInputMethodProperties, id, true); 1794a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1804a5f889f80b683446e498f244d0eadfd979ca5d0satok 1814a5f889f80b683446e498f244d0eadfd979ca5d0satok }) 1824a5f889f80b683446e498f244d0eadfd979ca5d0satok .setNegativeButton(android.R.string.cancel, 1834a5f889f80b683446e498f244d0eadfd979ca5d0satok new DialogInterface.OnClickListener() { 184e077d2b607032fb66a4a046aa4b46945d32d281esatok @Override 1854a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onClick(DialogInterface dialog, int which) { 1864a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1874a5f889f80b683446e498f244d0eadfd979ca5d0satok 1884a5f889f80b683446e498f244d0eadfd979ca5d0satok }) 1894a5f889f80b683446e498f244d0eadfd979ca5d0satok .create(); 1904a5f889f80b683446e498f244d0eadfd979ca5d0satok } else { 1914a5f889f80b683446e498f244d0eadfd979ca5d0satok if (mDialog.isShowing()) { 1924a5f889f80b683446e498f244d0eadfd979ca5d0satok mDialog.dismiss(); 1934a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1944a5f889f80b683446e498f244d0eadfd979ca5d0satok } 1954a5f889f80b683446e498f244d0eadfd979ca5d0satok mDialog.setMessage(getResources().getString( 1964a5f889f80b683446e498f244d0eadfd979ca5d0satok R.string.ime_security_warning, 1974a5f889f80b683446e498f244d0eadfd979ca5d0satok selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager()))); 1984a5f889f80b683446e498f244d0eadfd979ca5d0satok mDialog.show(); 1994a5f889f80b683446e498f244d0eadfd979ca5d0satok } else { 2009cd11a9aa5ac74ca89432655d019f68d789bc405satok InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled( 2019cd11a9aa5ac74ca89432655d019f68d789bc405satok this, mInputMethodProperties, id, false); 20274a5414b3c4473106ab2c043d52d8b55a9e4d0c5satok updateAutoSelectionCB(); 2034a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2044a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2054a5f889f80b683446e498f244d0eadfd979ca5d0satok return super.onPreferenceTreeClick(preferenceScreen, preference); 2064a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2074a5f889f80b683446e498f244d0eadfd979ca5d0satok 2084a5f889f80b683446e498f244d0eadfd979ca5d0satok @Override 2094a5f889f80b683446e498f244d0eadfd979ca5d0satok public void onDestroy() { 2104a5f889f80b683446e498f244d0eadfd979ca5d0satok super.onDestroy(); 2114a5f889f80b683446e498f244d0eadfd979ca5d0satok if (mDialog != null) { 2124a5f889f80b683446e498f244d0eadfd979ca5d0satok mDialog.dismiss(); 2134a5f889f80b683446e498f244d0eadfd979ca5d0satok mDialog = null; 2144a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2154a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2164a5f889f80b683446e498f244d0eadfd979ca5d0satok 2174a5f889f80b683446e498f244d0eadfd979ca5d0satok private void onCreateIMM() { 2184a5f889f80b683446e498f244d0eadfd979ca5d0satok InputMethodManager imm = (InputMethodManager) getSystemService( 2194a5f889f80b683446e498f244d0eadfd979ca5d0satok Context.INPUT_METHOD_SERVICE); 2204a5f889f80b683446e498f244d0eadfd979ca5d0satok 2214a5f889f80b683446e498f244d0eadfd979ca5d0satok // TODO: Change mInputMethodProperties to Map 2224a5f889f80b683446e498f244d0eadfd979ca5d0satok mInputMethodProperties = imm.getInputMethodList(); 2234a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2244a5f889f80b683446e498f244d0eadfd979ca5d0satok 2254a5f889f80b683446e498f244d0eadfd979ca5d0satok private PreferenceScreen createPreferenceHierarchy() { 2264a5f889f80b683446e498f244d0eadfd979ca5d0satok // Root 227f0ae329740eb66663b6f099ca24a13ea7572418csatok final PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity()); 228f0ae329740eb66663b6f099ca24a13ea7572418csatok final Context context = getActivity(); 2294a5f889f80b683446e498f244d0eadfd979ca5d0satok 2304a5f889f80b683446e498f244d0eadfd979ca5d0satok int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size()); 231c88a7ff1efd10374974e45768bde1658cc1d8483satok 2324a5f889f80b683446e498f244d0eadfd979ca5d0satok for (int i = 0; i < N; ++i) { 233c88a7ff1efd10374974e45768bde1658cc1d8483satok final InputMethodInfo imi = mInputMethodProperties.get(i); 2345a813ba7f99f1c797ead4a58fdf05f91296158a4Ken Wakasa final int subtypeCount = imi.getSubtypeCount(); 2355a813ba7f99f1c797ead4a58fdf05f91296158a4Ken Wakasa if (subtypeCount <= 1) continue; 2361c58c15e7a84b582b7d4d20c26824cabce80bce9satok final String imiId = imi.getId(); 2371c58c15e7a84b582b7d4d20c26824cabce80bce9satok // Add this subtype to the list when no IME is specified or when the IME of this 238c88a7ff1efd10374974e45768bde1658cc1d8483satok // subtype is the specified IME. 239c88a7ff1efd10374974e45768bde1658cc1d8483satok if (!TextUtils.isEmpty(mInputMethodId) && !mInputMethodId.equals(imiId)) { 240c88a7ff1efd10374974e45768bde1658cc1d8483satok continue; 241c88a7ff1efd10374974e45768bde1658cc1d8483satok } 24294bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok final PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(context); 2434a5f889f80b683446e498f244d0eadfd979ca5d0satok root.addPreference(keyboardSettingsCategory); 24494bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok final PackageManager pm = getPackageManager(); 24594bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok final CharSequence label = imi.loadLabel(pm); 246c88a7ff1efd10374974e45768bde1658cc1d8483satok 2471c58c15e7a84b582b7d4d20c26824cabce80bce9satok keyboardSettingsCategory.setTitle(label); 248c88a7ff1efd10374974e45768bde1658cc1d8483satok keyboardSettingsCategory.setKey(imiId); 2491c58c15e7a84b582b7d4d20c26824cabce80bce9satok // TODO: Use toggle Preference if images are ready. 25094bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok final CheckBoxPreference autoCB = new CheckBoxPreference(context); 2511c58c15e7a84b582b7d4d20c26824cabce80bce9satok mSubtypeAutoSelectionCBMap.put(imiId, autoCB); 2521c58c15e7a84b582b7d4d20c26824cabce80bce9satok keyboardSettingsCategory.addPreference(autoCB); 2531c58c15e7a84b582b7d4d20c26824cabce80bce9satok 25494bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok final PreferenceCategory activeInputMethodsCategory = new PreferenceCategory(context); 2551c58c15e7a84b582b7d4d20c26824cabce80bce9satok activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes); 2561c58c15e7a84b582b7d4d20c26824cabce80bce9satok root.addPreference(activeInputMethodsCategory); 2574a5f889f80b683446e498f244d0eadfd979ca5d0satok 25894bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok boolean isAutoSubtype = false; 25994bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok CharSequence autoSubtypeLabel = null; 26094bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok final ArrayList<Preference> subtypePreferences = new ArrayList<Preference>(); 2615a813ba7f99f1c797ead4a58fdf05f91296158a4Ken Wakasa if (subtypeCount > 0) { 2625a813ba7f99f1c797ead4a58fdf05f91296158a4Ken Wakasa for (int j = 0; j < subtypeCount; ++j) { 263f0ae329740eb66663b6f099ca24a13ea7572418csatok final InputMethodSubtype subtype = imi.getSubtypeAt(j); 264f0ae329740eb66663b6f099ca24a13ea7572418csatok final CharSequence subtypeLabel = subtype.getDisplayName(context, 265f0ae329740eb66663b6f099ca24a13ea7572418csatok imi.getPackageName(), imi.getServiceInfo().applicationInfo); 26694bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok if (subtype.overridesImplicitlyEnabledSubtype()) { 26794bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok if (!isAutoSubtype) { 26894bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok isAutoSubtype = true; 26994bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok autoSubtypeLabel = subtypeLabel; 27094bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } 27194bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } else { 272ae70ee49492bd89c949946562b43a75f3c81b0adsatok final CheckBoxPreference chkbxPref = new SubtypeCheckBoxPreference( 273ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka context, subtype.getLocale(), mSystemLocale, mCollator); 27494bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok chkbxPref.setKey(imiId + subtype.hashCode()); 27594bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok chkbxPref.setTitle(subtypeLabel); 27694bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok subtypePreferences.add(chkbxPref); 27794bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } 2784a5f889f80b683446e498f244d0eadfd979ca5d0satok } 279ae70ee49492bd89c949946562b43a75f3c81b0adsatok Collections.sort(subtypePreferences); 280ae70ee49492bd89c949946562b43a75f3c81b0adsatok for (int j = 0; j < subtypePreferences.size(); ++j) { 281ae70ee49492bd89c949946562b43a75f3c81b0adsatok activeInputMethodsCategory.addPreference(subtypePreferences.get(j)); 282ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 2831c58c15e7a84b582b7d4d20c26824cabce80bce9satok mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences); 2844a5f889f80b683446e498f244d0eadfd979ca5d0satok } 28594bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok if (isAutoSubtype) { 28694bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok if (TextUtils.isEmpty(autoSubtypeLabel)) { 28794bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok Log.w(TAG, "Title for auto subtype is empty."); 28894bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok autoCB.setTitle("---"); 28994bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } else { 29094bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok autoCB.setTitle(autoSubtypeLabel); 29194bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } 29294bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } else { 29394bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok autoCB.setTitle(R.string.use_system_language_to_select_input_method_subtypes); 29494bc76f1aa887e90b31f375cb1e9a2ecc3c59c8bsatok } 2954a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2964a5f889f80b683446e498f244d0eadfd979ca5d0satok return root; 2974a5f889f80b683446e498f244d0eadfd979ca5d0satok } 2981c58c15e7a84b582b7d4d20c26824cabce80bce9satok 2991c58c15e7a84b582b7d4d20c26824cabce80bce9satok private boolean isNoSubtypesExplicitlySelected(String imiId) { 3001c58c15e7a84b582b7d4d20c26824cabce80bce9satok boolean allSubtypesOff = true; 3011c58c15e7a84b582b7d4d20c26824cabce80bce9satok final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 3021c58c15e7a84b582b7d4d20c26824cabce80bce9satok for (Preference subtypePref: subtypePrefs) { 3031c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (subtypePref instanceof CheckBoxPreference 3041c58c15e7a84b582b7d4d20c26824cabce80bce9satok && ((CheckBoxPreference)subtypePref).isChecked()) { 3051c58c15e7a84b582b7d4d20c26824cabce80bce9satok allSubtypesOff = false; 3061c58c15e7a84b582b7d4d20c26824cabce80bce9satok break; 3071c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3081c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3091c58c15e7a84b582b7d4d20c26824cabce80bce9satok return allSubtypesOff; 3101c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3111c58c15e7a84b582b7d4d20c26824cabce80bce9satok 3121c58c15e7a84b582b7d4d20c26824cabce80bce9satok private void setSubtypeAutoSelectionEnabled(String imiId, boolean autoSelectionEnabled) { 31374a5414b3c4473106ab2c043d52d8b55a9e4d0c5satok CheckBoxPreference autoSelectionCB = mSubtypeAutoSelectionCBMap.get(imiId); 31474a5414b3c4473106ab2c043d52d8b55a9e4d0c5satok if (autoSelectionCB == null) return; 31574a5414b3c4473106ab2c043d52d8b55a9e4d0c5satok autoSelectionCB.setChecked(autoSelectionEnabled); 3161c58c15e7a84b582b7d4d20c26824cabce80bce9satok final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 3171c58c15e7a84b582b7d4d20c26824cabce80bce9satok for (Preference subtypePref: subtypePrefs) { 3181c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (subtypePref instanceof CheckBoxPreference) { 3191c58c15e7a84b582b7d4d20c26824cabce80bce9satok // When autoSelectionEnabled is true, all subtype prefs need to be disabled with 3201c58c15e7a84b582b7d4d20c26824cabce80bce9satok // implicitly checked subtypes. In case of false, all subtype prefs need to be 3211c58c15e7a84b582b7d4d20c26824cabce80bce9satok // enabled. 3221c58c15e7a84b582b7d4d20c26824cabce80bce9satok subtypePref.setEnabled(!autoSelectionEnabled); 3231c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (autoSelectionEnabled) { 3241c58c15e7a84b582b7d4d20c26824cabce80bce9satok ((CheckBoxPreference)subtypePref).setChecked(false); 3251c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3261c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3271c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3281c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (autoSelectionEnabled) { 3291c58c15e7a84b582b7d4d20c26824cabce80bce9satok InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(), 3301c58c15e7a84b582b7d4d20c26824cabce80bce9satok mInputMethodProperties, mHaveHardKeyboard); 3311c58c15e7a84b582b7d4d20c26824cabce80bce9satok setCheckedImplicitlyEnabledSubtypes(imiId); 3321c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3331c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3341c58c15e7a84b582b7d4d20c26824cabce80bce9satok 3351c58c15e7a84b582b7d4d20c26824cabce80bce9satok private void setCheckedImplicitlyEnabledSubtypes(String targetImiId) { 3361c58c15e7a84b582b7d4d20c26824cabce80bce9satok updateImplicitlyEnabledSubtypes(targetImiId, true); 3371c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3381c58c15e7a84b582b7d4d20c26824cabce80bce9satok 3391c58c15e7a84b582b7d4d20c26824cabce80bce9satok private void clearImplicitlyEnabledSubtypes(String targetImiId) { 3401c58c15e7a84b582b7d4d20c26824cabce80bce9satok updateImplicitlyEnabledSubtypes(targetImiId, false); 3411c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3421c58c15e7a84b582b7d4d20c26824cabce80bce9satok 3431c58c15e7a84b582b7d4d20c26824cabce80bce9satok private void updateImplicitlyEnabledSubtypes(String targetImiId, boolean check) { 3441c58c15e7a84b582b7d4d20c26824cabce80bce9satok // When targetImiId is null, apply to all subtypes of all IMEs 3451c58c15e7a84b582b7d4d20c26824cabce80bce9satok for (InputMethodInfo imi: mInputMethodProperties) { 3461c58c15e7a84b582b7d4d20c26824cabce80bce9satok String imiId = imi.getId(); 3471c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (targetImiId != null && !targetImiId.equals(imiId)) continue; 3481c58c15e7a84b582b7d4d20c26824cabce80bce9satok final CheckBoxPreference autoCB = mSubtypeAutoSelectionCBMap.get(imiId); 3491c58c15e7a84b582b7d4d20c26824cabce80bce9satok // No need to update implicitly enabled subtypes when the user has unchecked the 3501c58c15e7a84b582b7d4d20c26824cabce80bce9satok // "subtype auto selection". 3511c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (autoCB == null || !autoCB.isChecked()) continue; 3521c58c15e7a84b582b7d4d20c26824cabce80bce9satok final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId); 3531c58c15e7a84b582b7d4d20c26824cabce80bce9satok final List<InputMethodSubtype> implicitlyEnabledSubtypes = 3541c58c15e7a84b582b7d4d20c26824cabce80bce9satok mImm.getEnabledInputMethodSubtypeList(imi, true); 3551c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (subtypePrefs == null || implicitlyEnabledSubtypes == null) continue; 3561c58c15e7a84b582b7d4d20c26824cabce80bce9satok for (Preference subtypePref: subtypePrefs) { 3571c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (subtypePref instanceof CheckBoxPreference) { 3581c58c15e7a84b582b7d4d20c26824cabce80bce9satok CheckBoxPreference cb = (CheckBoxPreference)subtypePref; 3591c58c15e7a84b582b7d4d20c26824cabce80bce9satok cb.setChecked(false); 3601c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (check) { 3611c58c15e7a84b582b7d4d20c26824cabce80bce9satok for (InputMethodSubtype subtype: implicitlyEnabledSubtypes) { 3621c58c15e7a84b582b7d4d20c26824cabce80bce9satok String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode(); 3631c58c15e7a84b582b7d4d20c26824cabce80bce9satok if (cb.getKey().equals(implicitlyEnabledSubtypePrefKey)) { 3641c58c15e7a84b582b7d4d20c26824cabce80bce9satok cb.setChecked(true); 3651c58c15e7a84b582b7d4d20c26824cabce80bce9satok break; 3661c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3671c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3681c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3691c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3701c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3711c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3721c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3731c58c15e7a84b582b7d4d20c26824cabce80bce9satok 3741c58c15e7a84b582b7d4d20c26824cabce80bce9satok private void updateAutoSelectionCB() { 3751c58c15e7a84b582b7d4d20c26824cabce80bce9satok for (String imiId: mInputMethodAndSubtypePrefsMap.keySet()) { 3761c58c15e7a84b582b7d4d20c26824cabce80bce9satok setSubtypeAutoSelectionEnabled(imiId, isNoSubtypesExplicitlySelected(imiId)); 3771c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 3781c58c15e7a84b582b7d4d20c26824cabce80bce9satok setCheckedImplicitlyEnabledSubtypes(null); 3791c58c15e7a84b582b7d4d20c26824cabce80bce9satok } 380ae70ee49492bd89c949946562b43a75f3c81b0adsatok 381ae70ee49492bd89c949946562b43a75f3c81b0adsatok private static class SubtypeCheckBoxPreference extends CheckBoxPreference { 382ae70ee49492bd89c949946562b43a75f3c81b0adsatok private final boolean mIsSystemLocale; 383ae70ee49492bd89c949946562b43a75f3c81b0adsatok private final boolean mIsSystemLanguage; 384ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka private final Collator mCollator; 385ae70ee49492bd89c949946562b43a75f3c81b0adsatok 386ae70ee49492bd89c949946562b43a75f3c81b0adsatok public SubtypeCheckBoxPreference( 387ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka Context context, String subtypeLocale, String systemLocale, Collator collator) { 388ae70ee49492bd89c949946562b43a75f3c81b0adsatok super(context); 389ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (TextUtils.isEmpty(subtypeLocale)) { 390ae70ee49492bd89c949946562b43a75f3c81b0adsatok mIsSystemLocale = false; 391ae70ee49492bd89c949946562b43a75f3c81b0adsatok mIsSystemLanguage = false; 392ae70ee49492bd89c949946562b43a75f3c81b0adsatok } else { 393ae70ee49492bd89c949946562b43a75f3c81b0adsatok mIsSystemLocale = subtypeLocale.equals(systemLocale); 394ae70ee49492bd89c949946562b43a75f3c81b0adsatok mIsSystemLanguage = mIsSystemLocale 395ae70ee49492bd89c949946562b43a75f3c81b0adsatok || subtypeLocale.startsWith(systemLocale.substring(0, 2)); 396ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 397ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka mCollator = collator; 398ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 399ae70ee49492bd89c949946562b43a75f3c81b0adsatok 400ae70ee49492bd89c949946562b43a75f3c81b0adsatok @Override 401ae70ee49492bd89c949946562b43a75f3c81b0adsatok public int compareTo(Preference p) { 402ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (p instanceof SubtypeCheckBoxPreference) { 403ae70ee49492bd89c949946562b43a75f3c81b0adsatok final SubtypeCheckBoxPreference pref = ((SubtypeCheckBoxPreference)p); 404ae70ee49492bd89c949946562b43a75f3c81b0adsatok final CharSequence t0 = getTitle(); 405ae70ee49492bd89c949946562b43a75f3c81b0adsatok final CharSequence t1 = pref.getTitle(); 406ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (TextUtils.equals(t0, t1)) { 407ae70ee49492bd89c949946562b43a75f3c81b0adsatok return 0; 408ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 409ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (mIsSystemLocale) { 410ae70ee49492bd89c949946562b43a75f3c81b0adsatok return -1; 411ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 412ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (pref.mIsSystemLocale) { 413ae70ee49492bd89c949946562b43a75f3c81b0adsatok return 1; 414ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 415ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (mIsSystemLanguage) { 416ae70ee49492bd89c949946562b43a75f3c81b0adsatok return -1; 417ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 418ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (pref.mIsSystemLanguage) { 419ae70ee49492bd89c949946562b43a75f3c81b0adsatok return 1; 420ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 421ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (TextUtils.isEmpty(t0)) { 422ae70ee49492bd89c949946562b43a75f3c81b0adsatok return 1; 423ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 424ae70ee49492bd89c949946562b43a75f3c81b0adsatok if (TextUtils.isEmpty(t1)) { 425ae70ee49492bd89c949946562b43a75f3c81b0adsatok return -1; 426ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 427ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka return mCollator.compare(t0.toString(), t1.toString()); 428ae70ee49492bd89c949946562b43a75f3c81b0adsatok } else { 429ae70ee49492bd89c949946562b43a75f3c81b0adsatok Log.w(TAG, "Illegal preference type."); 430ef120bea7b8cb3b891ae3f39d7a97989c107a16fSatoshi Kataoka return super.compareTo(p); 431ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 432ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 433ae70ee49492bd89c949946562b43a75f3c81b0adsatok } 4344a5f889f80b683446e498f244d0eadfd979ca5d0satok} 435