InputMethodPreference.java revision 4c5fdcc3f70ac5496b21d7db57f62ee9db4e6a19
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.DialogInterface;
25import android.content.Intent;
26import android.content.res.Configuration;
27import android.os.Bundle;
28import android.preference.CheckBoxPreference;
29import android.preference.PreferenceActivity;
30import android.provider.Settings;
31import android.text.TextUtils;
32import android.util.Log;
33import android.view.View;
34import android.view.View.OnClickListener;
35import android.view.View.OnLongClickListener;
36import android.view.inputmethod.InputMethodInfo;
37import android.view.inputmethod.InputMethodManager;
38import android.view.inputmethod.InputMethodSubtype;
39import android.widget.ImageView;
40import android.widget.TextView;
41
42import java.util.Comparator;
43import java.util.List;
44
45public class InputMethodPreference extends CheckBoxPreference
46        implements Comparator<InputMethodPreference> {
47    private static final String TAG = InputMethodPreference.class.getSimpleName();
48    private static final float DISABLED_ALPHA = 0.4f;
49    private final SettingsPreferenceFragment mFragment;
50    private final InputMethodInfo mImi;
51    private final InputMethodManager mImm;
52    private final Intent mSettingsIntent;
53    private final boolean mIsSystemIme;
54
55    private AlertDialog mDialog = null;
56    private ImageView mInputMethodSettingsButton;
57    private TextView mTitleText;
58    private TextView mSummaryText;
59    private View mInputMethodPref;
60
61    public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent,
62            InputMethodManager imm, InputMethodInfo imi, int imiCount) {
63        super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle);
64        setLayoutResource(R.layout.preference_inputmethod);
65        setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
66        mFragment = fragment;
67        mSettingsIntent = settingsIntent;
68        mImm = imm;
69        mImi = imi;
70        updateSummary();
71        mIsSystemIme = InputMethodAndSubtypeUtil.isSystemIme(imi);
72        final boolean isAuxIme = InputMethodAndSubtypeUtil.isAuxiliaryIme(imi);
73        if (imiCount <= 1 || (mIsSystemIme && !isAuxIme)) {
74            setEnabled(false);
75        }
76    }
77
78    @Override
79    protected void onBindView(View view) {
80        super.onBindView(view);
81        mInputMethodPref = view.findViewById(R.id.inputmethod_pref);
82        mInputMethodPref.setOnClickListener(
83                new OnClickListener() {
84                    @Override
85                    public void onClick(View arg0) {
86                        if (isChecked()) {
87                            setChecked(false);
88                        } else {
89                            if (mIsSystemIme) {
90                                setChecked(true);
91                            } else {
92                                showSecurityWarnDialog(mImi, InputMethodPreference.this);
93                            }
94                        }
95                    }
96                });
97        mInputMethodSettingsButton = (ImageView)view.findViewById(R.id.inputmethod_settings);
98        mTitleText = (TextView)view.findViewById(android.R.id.title);
99        mSummaryText = (TextView)view.findViewById(android.R.id.summary);
100        if (mSettingsIntent != null) {
101            mInputMethodSettingsButton.setOnClickListener(
102                    new OnClickListener() {
103                        @Override
104                        public void onClick(View arg0) {
105                            mFragment.startActivity(mSettingsIntent);
106                        }
107                    });
108        }
109        final boolean hasSubtypes = mImi.getSubtypeCount() > 1;
110        final String imiId = mImi.getId();
111        if (hasSubtypes) {
112            final OnLongClickListener listener = new OnLongClickListener() {
113                @Override
114                public boolean onLongClick(View arg0) {
115                    final Bundle bundle = new Bundle();
116                    bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
117                    startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
118                            0, bundle);
119                    return true;
120                }
121            };
122            mInputMethodSettingsButton.setOnLongClickListener(listener);
123        }
124        if (mSettingsIntent == null) {
125            mInputMethodSettingsButton.setVisibility(View.GONE);
126        } else {
127            enableSettingsButton();
128        }
129    }
130
131    @Override
132    public void setEnabled(boolean enabled) {
133        super.setEnabled(enabled);
134        enableSettingsButton();
135    }
136
137    private void enableSettingsButton() {
138        if (mInputMethodSettingsButton != null) {
139            final boolean checked = isChecked();
140            mInputMethodSettingsButton.setEnabled(checked);
141            mInputMethodSettingsButton.setClickable(checked);
142            mInputMethodSettingsButton.setFocusable(checked);
143            if (!checked) {
144                mInputMethodSettingsButton.setAlpha(DISABLED_ALPHA);
145            }
146        }
147        if (mTitleText != null) {
148            mTitleText.setEnabled(true);
149        }
150        if (mSummaryText != null) {
151            mSummaryText.setEnabled(true);
152        }
153    }
154
155    public static boolean startFragment(
156            Fragment fragment, String fragmentClass, int requestCode, Bundle extras) {
157        if (fragment.getActivity() instanceof PreferenceActivity) {
158            PreferenceActivity preferenceActivity = (PreferenceActivity)fragment.getActivity();
159            preferenceActivity.startPreferencePanel(fragmentClass, extras, 0, null, fragment,
160                    requestCode);
161            return true;
162        } else {
163            Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
164                    + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
165                    + ")");
166            return false;
167        }
168    }
169
170    public String getSummaryString() {
171        final StringBuilder builder = new StringBuilder();
172        final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true);
173        for (InputMethodSubtype subtype : subtypes) {
174            if (builder.length() > 0) {
175                builder.append(", ");
176            }
177            final CharSequence subtypeLabel = subtype.getDisplayName(mFragment.getActivity(),
178                    mImi.getPackageName(), mImi.getServiceInfo().applicationInfo);
179            builder.append(subtypeLabel);
180        }
181        return builder.toString();
182    }
183
184    public void updateSummary() {
185        final String summary = getSummaryString();
186        if (TextUtils.isEmpty(summary)) {
187            return;
188        }
189        setSummary(summary);
190    }
191
192    @Override
193    public void setChecked(boolean checked) {
194        super.setChecked(checked);
195        saveImeSettings();
196    }
197
198    private void showSecurityWarnDialog(InputMethodInfo imi, final CheckBoxPreference chkPref) {
199        if (mDialog != null && mDialog.isShowing()) {
200            mDialog.dismiss();
201        }
202        mDialog = (new AlertDialog.Builder(mFragment.getActivity()))
203                .setTitle(android.R.string.dialog_alert_title)
204                .setIcon(android.R.drawable.ic_dialog_alert)
205                .setCancelable(true)
206                .setPositiveButton(android.R.string.ok,
207                        new DialogInterface.OnClickListener() {
208                    @Override
209                    public void onClick(DialogInterface dialog, int which) {
210                        chkPref.setChecked(true);
211                    }
212                })
213                .setNegativeButton(android.R.string.cancel,
214                        new DialogInterface.OnClickListener() {
215                    @Override
216                    public void onClick(DialogInterface dialog, int which) {
217                    }
218                })
219                .create();
220        mDialog.setMessage(mFragment.getResources().getString(R.string.ime_security_warning,
221                imi.getServiceInfo().applicationInfo.loadLabel(
222                        mFragment.getActivity().getPackageManager())));
223        mDialog.show();
224    }
225
226    @Override
227    public int compare(InputMethodPreference arg0, InputMethodPreference arg1) {
228        if (arg0.isEnabled() == arg0.isEnabled()) {
229            return arg0.mImi.getId().compareTo(arg1.mImi.getId());
230        } else {
231            // Prefer system IMEs
232            return arg0.isEnabled() ? 1 : -1;
233        }
234    }
235
236    private void saveImeSettings() {
237        InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
238                mFragment, mFragment.getActivity().getContentResolver(), mImm.getInputMethodList(),
239                mFragment.getResources().getConfiguration().keyboard
240                        == Configuration.KEYBOARD_QWERTY);
241    }
242}
243