InputMethodPreference.java revision 1c2b175d7ab8da48a12191c4930bd4ed451a9952
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        mSummaryText = (TextView)view.findViewById(android.R.id.summary);
101        if (mSettingsIntent != null) {
102            mInputMethodSettingsButton.setOnClickListener(
103                    new OnClickListener() {
104                        @Override
105                        public void onClick(View arg0) {
106                            try {
107                                mFragment.startActivity(mSettingsIntent);
108                            } catch (ActivityNotFoundException e) {
109                                Log.d(TAG, "IME's Settings Activity Not Found: " + e);
110                                // If the IME's settings activity does not exist, we can just
111                                // do nothing...
112                            }
113                        }
114                    });
115        }
116        final boolean hasSubtypes = mImi.getSubtypeCount() > 1;
117        final String imiId = mImi.getId();
118        if (hasSubtypes) {
119            final OnLongClickListener listener = new OnLongClickListener() {
120                @Override
121                public boolean onLongClick(View arg0) {
122                    final Bundle bundle = new Bundle();
123                    bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
124                    startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
125                            0, bundle);
126                    return true;
127                }
128            };
129            mInputMethodSettingsButton.setOnLongClickListener(listener);
130        }
131        if (mSettingsIntent == null) {
132            mInputMethodSettingsButton.setVisibility(View.GONE);
133        } else {
134            enableSettingsButton();
135        }
136    }
137
138    @Override
139    public void setEnabled(boolean enabled) {
140        super.setEnabled(enabled);
141        enableSettingsButton();
142    }
143
144    private void enableSettingsButton() {
145        if (mInputMethodSettingsButton != null) {
146            final boolean checked = isChecked();
147            mInputMethodSettingsButton.setEnabled(checked);
148            mInputMethodSettingsButton.setClickable(checked);
149            mInputMethodSettingsButton.setFocusable(checked);
150            if (!checked) {
151                mInputMethodSettingsButton.setAlpha(DISABLED_ALPHA);
152            }
153        }
154        if (mTitleText != null) {
155            mTitleText.setEnabled(true);
156        }
157        if (mSummaryText != null) {
158            mSummaryText.setEnabled(true);
159        }
160    }
161
162    public static boolean startFragment(
163            Fragment fragment, String fragmentClass, int requestCode, Bundle extras) {
164        if (fragment.getActivity() instanceof PreferenceActivity) {
165            PreferenceActivity preferenceActivity = (PreferenceActivity)fragment.getActivity();
166            preferenceActivity.startPreferencePanel(fragmentClass, extras, 0, null, fragment,
167                    requestCode);
168            return true;
169        } else {
170            Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
171                    + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
172                    + ")");
173            return false;
174        }
175    }
176
177    public String getSummaryString() {
178        final StringBuilder builder = new StringBuilder();
179        final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true);
180        for (InputMethodSubtype subtype : subtypes) {
181            if (builder.length() > 0) {
182                builder.append(", ");
183            }
184            final CharSequence subtypeLabel = subtype.getDisplayName(mFragment.getActivity(),
185                    mImi.getPackageName(), mImi.getServiceInfo().applicationInfo);
186            builder.append(subtypeLabel);
187        }
188        return builder.toString();
189    }
190
191    public void updateSummary() {
192        final String summary = getSummaryString();
193        if (TextUtils.isEmpty(summary)) {
194            return;
195        }
196        setSummary(summary);
197    }
198
199    @Override
200    public void setChecked(boolean checked) {
201        super.setChecked(checked);
202        saveImeSettings();
203    }
204
205    private void showSecurityWarnDialog(InputMethodInfo imi, final CheckBoxPreference chkPref) {
206        if (mDialog != null && mDialog.isShowing()) {
207            mDialog.dismiss();
208        }
209        mDialog = (new AlertDialog.Builder(mFragment.getActivity()))
210                .setTitle(android.R.string.dialog_alert_title)
211                .setIcon(android.R.drawable.ic_dialog_alert)
212                .setCancelable(true)
213                .setPositiveButton(android.R.string.ok,
214                        new DialogInterface.OnClickListener() {
215                    @Override
216                    public void onClick(DialogInterface dialog, int which) {
217                        chkPref.setChecked(true);
218                    }
219                })
220                .setNegativeButton(android.R.string.cancel,
221                        new DialogInterface.OnClickListener() {
222                    @Override
223                    public void onClick(DialogInterface dialog, int which) {
224                    }
225                })
226                .create();
227        mDialog.setMessage(mFragment.getResources().getString(R.string.ime_security_warning,
228                imi.getServiceInfo().applicationInfo.loadLabel(
229                        mFragment.getActivity().getPackageManager())));
230        mDialog.show();
231    }
232
233    @Override
234    public int compare(InputMethodPreference arg0, InputMethodPreference arg1) {
235        if (arg0.isEnabled() == arg0.isEnabled()) {
236            return arg0.mImi.getId().compareTo(arg1.mImi.getId());
237        } else {
238            // Prefer system IMEs
239            return arg0.isEnabled() ? 1 : -1;
240        }
241    }
242
243    private void saveImeSettings() {
244        InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
245                mFragment, mFragment.getActivity().getContentResolver(), mImm.getInputMethodList(),
246                mFragment.getResources().getConfiguration().keyboard
247                        == Configuration.KEYBOARD_QWERTY);
248    }
249}
250