InputMethodPreference.java revision 88b75f740a1c75040bd7339e5ef9d5abdb50014d
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings.inputmethod;
18
19import com.android.settings.R;
20import com.android.settings.SettingsPreferenceFragment;
21
22import android.app.AlertDialog;
23import android.app.Fragment;
24import android.content.ActivityNotFoundException;
25import android.content.DialogInterface;
26import android.content.Intent;
27import android.content.res.Configuration;
28import android.os.Bundle;
29import android.preference.CheckBoxPreference;
30import android.preference.PreferenceActivity;
31import android.provider.Settings;
32import android.text.TextUtils;
33import android.util.Log;
34import android.view.View;
35import android.view.View.OnClickListener;
36import android.view.View.OnLongClickListener;
37import android.view.inputmethod.InputMethodInfo;
38import android.view.inputmethod.InputMethodManager;
39import android.view.inputmethod.InputMethodSubtype;
40import android.widget.ImageView;
41import android.widget.TextView;
42
43import java.util.Comparator;
44import java.util.List;
45
46public class InputMethodPreference extends CheckBoxPreference
47        implements Comparator<InputMethodPreference> {
48    private static final String TAG = InputMethodPreference.class.getSimpleName();
49    private static final float DISABLED_ALPHA = 0.4f;
50    private final SettingsPreferenceFragment mFragment;
51    private final InputMethodInfo mImi;
52    private final InputMethodManager mImm;
53    private final Intent mSettingsIntent;
54    private final boolean mIsSystemIme;
55
56    private AlertDialog mDialog = null;
57    private ImageView mInputMethodSettingsButton;
58    private TextView mTitleText;
59    private TextView mSummaryText;
60    private View mInputMethodPref;
61
62    public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent,
63            InputMethodManager imm, InputMethodInfo imi, int imiCount) {
64        super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle);
65        setLayoutResource(R.layout.preference_inputmethod);
66        setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
67        mFragment = fragment;
68        mSettingsIntent = settingsIntent;
69        mImm = imm;
70        mImi = imi;
71        updateSummary();
72        mIsSystemIme = InputMethodAndSubtypeUtil.isSystemIme(imi);
73        final boolean isAuxIme = InputMethodAndSubtypeUtil.isAuxiliaryIme(imi);
74        if (imiCount <= 1 || (mIsSystemIme && !isAuxIme)) {
75            setEnabled(false);
76        }
77    }
78
79    @Override
80    protected void onBindView(View view) {
81        super.onBindView(view);
82        mInputMethodPref = view.findViewById(R.id.inputmethod_pref);
83        mInputMethodPref.setOnClickListener(
84                new OnClickListener() {
85                    @Override
86                    public void onClick(View arg0) {
87                        if (isChecked()) {
88                            setChecked(false);
89                        } else {
90                            if (mIsSystemIme) {
91                                setChecked(true);
92                            } else {
93                                showSecurityWarnDialog(mImi, InputMethodPreference.this);
94                            }
95                        }
96                    }
97                });
98        mInputMethodSettingsButton = (ImageView)view.findViewById(R.id.inputmethod_settings);
99        mTitleText = (TextView)view.findViewById(android.R.id.title);
100
101        final boolean hasSubtypes = mImi.getSubtypeCount() > 1;
102        final String imiId = mImi.getId();
103        mSummaryText = (TextView)view.findViewById(android.R.id.summary);
104        mSummaryText.setOnClickListener(new OnClickListener() {
105            @Override
106            public void onClick(View arg0) {
107                final Bundle bundle = new Bundle();
108                bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
109                startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
110                        0, bundle);
111            }
112        });
113        if (mSettingsIntent != null) {
114            mInputMethodSettingsButton.setOnClickListener(
115                    new OnClickListener() {
116                        @Override
117                        public void onClick(View arg0) {
118                            try {
119                                mFragment.startActivity(mSettingsIntent);
120                            } catch (ActivityNotFoundException e) {
121                                Log.d(TAG, "IME's Settings Activity Not Found: " + e);
122                                // If the IME's settings activity does not exist, we can just
123                                // do nothing...
124                            }
125                        }
126                    });
127        }
128        if (hasSubtypes) {
129            final OnLongClickListener listener = new OnLongClickListener() {
130                @Override
131                public boolean onLongClick(View arg0) {
132                    final Bundle bundle = new Bundle();
133                    bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
134                    startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
135                            0, bundle);
136                    return true;
137                }
138            };
139            mInputMethodSettingsButton.setOnLongClickListener(listener);
140        }
141        if (mSettingsIntent == null) {
142            mInputMethodSettingsButton.setVisibility(View.GONE);
143        } else {
144            enableSettingsButton();
145        }
146    }
147
148    @Override
149    public void setEnabled(boolean enabled) {
150        super.setEnabled(enabled);
151        enableSettingsButton();
152    }
153
154    private void enableSettingsButton() {
155        final boolean checked = isChecked();
156        if (mInputMethodSettingsButton != null) {
157            mInputMethodSettingsButton.setEnabled(checked);
158            mInputMethodSettingsButton.setClickable(checked);
159            mInputMethodSettingsButton.setFocusable(checked);
160            if (!checked) {
161                mInputMethodSettingsButton.setAlpha(DISABLED_ALPHA);
162            }
163        }
164        if (mTitleText != null) {
165            mTitleText.setEnabled(true);
166        }
167        if (mSummaryText != null) {
168            mSummaryText.setEnabled(checked);
169            mSummaryText.setClickable(checked);
170        }
171    }
172
173    public static boolean startFragment(
174            Fragment fragment, String fragmentClass, int requestCode, Bundle extras) {
175        if (fragment.getActivity() instanceof PreferenceActivity) {
176            PreferenceActivity preferenceActivity = (PreferenceActivity)fragment.getActivity();
177            preferenceActivity.startPreferencePanel(fragmentClass, extras, 0, null, fragment,
178                    requestCode);
179            return true;
180        } else {
181            Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
182                    + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
183                    + ")");
184            return false;
185        }
186    }
187
188    public String getSummaryString() {
189        final StringBuilder builder = new StringBuilder();
190        final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true);
191        for (InputMethodSubtype subtype : subtypes) {
192            if (builder.length() > 0) {
193                builder.append(", ");
194            }
195            final CharSequence subtypeLabel = subtype.getDisplayName(mFragment.getActivity(),
196                    mImi.getPackageName(), mImi.getServiceInfo().applicationInfo);
197            builder.append(subtypeLabel);
198        }
199        return builder.toString();
200    }
201
202    public void updateSummary() {
203        final String summary = getSummaryString();
204        if (TextUtils.isEmpty(summary)) {
205            return;
206        }
207        setSummary(summary);
208    }
209
210    @Override
211    public void setChecked(boolean checked) {
212        super.setChecked(checked);
213        saveImeSettings();
214    }
215
216    private void showSecurityWarnDialog(InputMethodInfo imi, final CheckBoxPreference chkPref) {
217        if (mDialog != null && mDialog.isShowing()) {
218            mDialog.dismiss();
219        }
220        mDialog = (new AlertDialog.Builder(mFragment.getActivity()))
221                .setTitle(android.R.string.dialog_alert_title)
222                .setIcon(android.R.drawable.ic_dialog_alert)
223                .setCancelable(true)
224                .setPositiveButton(android.R.string.ok,
225                        new DialogInterface.OnClickListener() {
226                    @Override
227                    public void onClick(DialogInterface dialog, int which) {
228                        chkPref.setChecked(true);
229                    }
230                })
231                .setNegativeButton(android.R.string.cancel,
232                        new DialogInterface.OnClickListener() {
233                    @Override
234                    public void onClick(DialogInterface dialog, int which) {
235                    }
236                })
237                .create();
238        mDialog.setMessage(mFragment.getResources().getString(R.string.ime_security_warning,
239                imi.getServiceInfo().applicationInfo.loadLabel(
240                        mFragment.getActivity().getPackageManager())));
241        mDialog.show();
242    }
243
244    @Override
245    public int compare(InputMethodPreference arg0, InputMethodPreference arg1) {
246        if (arg0.isEnabled() == arg0.isEnabled()) {
247            return arg0.mImi.getId().compareTo(arg1.mImi.getId());
248        } else {
249            // Prefer system IMEs
250            return arg0.isEnabled() ? 1 : -1;
251        }
252    }
253
254    private void saveImeSettings() {
255        InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
256                mFragment, mFragment.getActivity().getContentResolver(), mImm.getInputMethodList(),
257                mFragment.getResources().getConfiguration().keyboard
258                        == Configuration.KEYBOARD_QWERTY);
259    }
260}
261