Implement new UI for IME settings

Bug: 4645160

Change-Id: If9046e7e96732f6ee4c0594cc66622b6462bdec9
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d92e14f..c6901b2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -356,6 +356,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <action android:name="com.android.settings.VOICE_INPUT_OUTPUT_SETTINGS" />
+                <action android:name="android.settings.INPUT_METHOD_SETTINGS" />
                 <category android:name="android.intent.category.VOICE_LAUNCH" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="com.android.settings.SHORTCUT" />
@@ -391,23 +392,6 @@
             </intent-filter>
         </activity>
 
-        <activity android:name="Settings$InputMethodConfigActivity"
-                android:theme="@android:style/Theme.Holo"
-                android:label="@string/configure_input_method"
-                android:clearTaskOnLaunch="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <action android:name="android.settings.INPUT_METHOD_SETTINGS" />
-                <category android:name="android.intent.category.VOICE_LAUNCH" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="com.android.settings.SHORTCUT" />
-            </intent-filter>
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                android:value="com.android.settings.inputmethod.InputMethodConfig" />
-            <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID"
-                android:resource="@id/language_settings" />
-        </activity>
-
         <activity android:name="Settings$UserDictionarySettingsActivity"
                 android:theme="@android:style/Theme.Holo"
                 android:label="@string/user_dict_settings_titlebar"
diff --git a/res/layout/preference_inputmethod.xml b/res/layout/preference_inputmethod.xml
new file mode 100644
index 0000000..227b165
--- /dev/null
+++ b/res/layout/preference_inputmethod.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical">
+    <LinearLayout
+        android:id="@+id/inputmethod_pref"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center_vertical"
+        android:clickable="true"
+        android:focusable="true"
+        android:background="?android:attr/selectableItemBackground">
+        <LinearLayout
+            android:id="@android:id/widget_frame"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="10dip"
+            android:gravity="center_vertical"
+            android:orientation="vertical" />
+        <RelativeLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="15dip"
+            android:layout_marginRight="6dip"
+            android:layout_marginTop="6dip"
+            android:layout_marginBottom="6dip"
+            android:layout_weight="1">
+            <TextView
+                android:id="@+android:id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"/>
+            <TextView
+                android:id="@android:id/summary"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@android:id/title"
+                android:layout_alignLeft="@android:id/title"
+                android:visibility="gone"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:textSize="13sp"
+                android:textColor="?android:attr/textColorSecondary"
+                android:maxLines="4" />
+        </RelativeLayout>
+    </LinearLayout>
+    <View
+        android:layout_width="2dip"
+        android:layout_height="match_parent"
+        android:layout_marginTop="5dip"
+        android:layout_marginBottom="5dip"
+        android:background="@android:drawable/divider_horizontal_dark" />
+    <ImageView
+        android:id="@+id/inputmethod_settings"
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:paddingLeft="15dip"
+        android:paddingRight="?android:attr/scrollbarSize"
+        android:src="@drawable/ic_sysbar_quicksettings"
+        android:layout_gravity="center"
+        android:clickable="true"
+        android:focusable="true"
+        android:background="?android:attr/selectableItemBackground" />
+</LinearLayout>
diff --git a/res/layout/preference_inputmethod_widget.xml b/res/layout/preference_inputmethod_widget.xml
new file mode 100644
index 0000000..ee573ad
--- /dev/null
+++ b/res/layout/preference_inputmethod_widget.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<CheckBox
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+android:id/checkbox"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:focusable="false"
+    android:clickable="false"/>
\ No newline at end of file
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 130fa03..0f73abf 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -150,4 +150,9 @@
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
     </style>
+
+    <style name="InputMethodPreferenceStyle">
+        <item name="android:layout">@layout/preference_inputmethod</item>
+        <item name="android:widgetLayout">@layout/preference_inputmethod_widget</item>
+    </style>
 </resources>
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index 1b5f039..fdf87fc 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -32,6 +32,35 @@
 
     </PreferenceCategory>
 
+    <PreferenceCategory android:key="keyboard_settings_category"
+            android:title="@string/keyboard_settings_category">
+        <PreferenceScreen android:key="current_input_method"
+                android:title="@string/current_input_method" />
+    </PreferenceCategory>
+    <PreferenceCategory
+            android:key="hard_keyboard"
+            android:title="@string/builtin_keyboard_settings_title"
+            android:persistent="false">
+        <CheckBoxPreference
+                android:key="auto_replace"
+                android:title="@string/auto_replace"
+                android:summaryOn="@string/auto_replace_summary"
+                android:summaryOff="@string/auto_replace_summary"
+                android:persistent="false"/>
+        <CheckBoxPreference
+                android:key="auto_caps"
+                android:title="@string/auto_caps"
+                android:summaryOn="@string/auto_caps_summary"
+                android:summaryOff="@string/auto_caps_summary"
+                android:persistent="false"/>
+        <CheckBoxPreference
+                android:key="auto_punctuate"
+                android:title="@string/auto_punctuate"
+                android:summaryOn="@string/auto_punctuate_summary"
+                android:summaryOff="@string/auto_punctuate_summary"
+                android:persistent="false"/>
+    </PreferenceCategory>
+
     <PreferenceCategory android:key="voice_input_category"
             android:title="@string/voice_input_category" >
 
@@ -54,24 +83,6 @@
                 android:title="@string/tts_settings_title" />
     </PreferenceCategory>
 
-    <PreferenceCategory android:key="keyboard_settings_category"
-            android:title="@string/keyboard_settings_category">
-        <PreferenceScreen android:key="current_input_method"
-                android:title="@string/current_input_method" />
-
-        <ListPreference android:key="input_method_selector"
-                android:title="@string/input_method_selector"
-                android:persistent="true"
-                android:entryValues="@array/input_method_selector_values"
-                android:entries="@array/input_method_selector_titles"
-                android:defaultValue="@string/input_method_selector_visibility_default_value"/>
-
-        <PreferenceScreen android:key="configure_input_method"
-                android:title="@string/configure_input_method">
-                <intent android:action="android.settings.INPUT_METHOD_SETTINGS"/>
-        </PreferenceScreen>
-    </PreferenceCategory>
-
     <PreferenceCategory android:key="pointer_settings_category"
             android:title="@string/pointer_settings_category">
         <com.android.settings.PointerSpeedPreference
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 69e6fad..16531e3 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -544,7 +544,6 @@
     public static class StorageSettingsActivity extends Settings { /* empty */ }
     public static class WifiSettingsActivity extends Settings { /* empty */ }
     public static class InputMethodAndLanguageSettingsActivity extends Settings { /* empty */ }
-    public static class InputMethodConfigActivity extends Settings { /* empty */ }
     public static class InputMethodAndSubtypeEnablerActivity extends Settings { /* empty */ }
     public static class LocalePickerActivity extends Settings { /* empty */ }
     public static class UserDictionarySettingsActivity extends Settings { /* empty */ }
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 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 @@
     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 @@
         } 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 @@
     @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);
             }
         }
 
-        updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_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);
+            }
+        }
+
+        // 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 @@
                         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 @@
 
     @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/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..75a32a0
--- /dev/null
+++ b/src/com/android/settings/inputmethod/InputMethodPreference.java
@@ -0,0 +1,254 @@
+/*
+ * 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 int subtypeCount = imi.getSubtypeCount();
+        boolean onlyAux = true;
+        if (subtypeCount == 0) {
+            onlyAux = false;
+        } else {
+            for (int i = 0; i < subtypeCount; ++i) {
+                final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                if (!subtype.isAuxiliary()) {
+                    onlyAux = false;
+                    break;
+                }
+            }
+        }
+        if (imiCount <= 1 || (mIsSystemIme && !onlyAux)) {
+            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);
+    }
+}