• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.settings.inputmethod;
18 
19 import com.android.settings.R;
20 import com.android.settings.SettingsPreferenceFragment;
21 
22 import android.app.AlertDialog;
23 import android.app.Fragment;
24 import android.content.ActivityNotFoundException;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.res.Configuration;
28 import android.os.Bundle;
29 import android.preference.CheckBoxPreference;
30 import android.preference.PreferenceActivity;
31 import android.provider.Settings;
32 import android.text.TextUtils;
33 import android.util.Log;
34 import android.view.View;
35 import android.view.View.OnClickListener;
36 import android.view.View.OnLongClickListener;
37 import android.view.inputmethod.InputMethodInfo;
38 import android.view.inputmethod.InputMethodManager;
39 import android.view.inputmethod.InputMethodSubtype;
40 import android.widget.ImageView;
41 import android.widget.TextView;
42 import android.widget.Toast;
43 
44 import java.util.Comparator;
45 import java.util.List;
46 
47 public class InputMethodPreference extends CheckBoxPreference
48         implements Comparator<InputMethodPreference> {
49     private static final String TAG = InputMethodPreference.class.getSimpleName();
50     private static final float DISABLED_ALPHA = 0.4f;
51     private final SettingsPreferenceFragment mFragment;
52     private final InputMethodInfo mImi;
53     private final InputMethodManager mImm;
54     private final Intent mSettingsIntent;
55     private final boolean mAlwaysChecked;
56     private final boolean mIsSystemIme;
57 
58     private AlertDialog mDialog = null;
59     private ImageView mInputMethodSettingsButton;
60     private TextView mTitleText;
61     private TextView mSummaryText;
62     private View mInputMethodPref;
63 
64     private final OnClickListener mPrefOnclickListener = new OnClickListener() {
65         @Override
66         public void onClick(View arg0) {
67             if (!isEnabled()) {
68                 return;
69             }
70             if (isChecked()) {
71                 setChecked(false, true /* save */);
72             } else {
73                 if (mIsSystemIme) {
74                     setChecked(true, true /* save */);
75                 } else {
76                     showSecurityWarnDialog(mImi, InputMethodPreference.this);
77                 }
78             }
79         }
80     };
81 
InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent, InputMethodManager imm, InputMethodInfo imi, int imiCount)82     public InputMethodPreference(SettingsPreferenceFragment fragment, Intent settingsIntent,
83             InputMethodManager imm, InputMethodInfo imi, int imiCount) {
84         super(fragment.getActivity(), null, R.style.InputMethodPreferenceStyle);
85         setLayoutResource(R.layout.preference_inputmethod);
86         setWidgetLayoutResource(R.layout.preference_inputmethod_widget);
87         mFragment = fragment;
88         mSettingsIntent = settingsIntent;
89         mImm = imm;
90         mImi = imi;
91         updateSummary();
92         mAlwaysChecked = InputMethodAndSubtypeUtil.isAlwaysCheckedIme(
93                 imi, fragment.getActivity(), imiCount);
94         mIsSystemIme = InputMethodAndSubtypeUtil.isSystemIme(imi);
95         if (mAlwaysChecked) {
96             setEnabled(false);
97         }
98     }
99 
100     @Override
onBindView(View view)101     protected void onBindView(View view) {
102         super.onBindView(view);
103         mInputMethodPref = view.findViewById(R.id.inputmethod_pref);
104         mInputMethodPref.setOnClickListener(mPrefOnclickListener);
105         mInputMethodSettingsButton = (ImageView)view.findViewById(R.id.inputmethod_settings);
106         mTitleText = (TextView)view.findViewById(android.R.id.title);
107         mSummaryText = (TextView)view.findViewById(android.R.id.summary);
108         final boolean hasSubtypes = mImi.getSubtypeCount() > 1;
109         final String imiId = mImi.getId();
110         if (hasSubtypes) {
111             mInputMethodPref.setOnLongClickListener(new OnLongClickListener() {
112                 @Override
113                 public boolean onLongClick(View arg0) {
114                     final Bundle bundle = new Bundle();
115                     bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
116                     startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
117                             0, bundle);
118                     return true;
119                 }
120             });
121         }
122 
123         if (mSettingsIntent != null) {
124             mInputMethodSettingsButton.setOnClickListener(
125                     new OnClickListener() {
126                         @Override
127                         public void onClick(View arg0) {
128                             try {
129                                 mFragment.startActivity(mSettingsIntent);
130                             } catch (ActivityNotFoundException e) {
131                                 Log.d(TAG, "IME's Settings Activity Not Found: " + e);
132                                 final String msg = mFragment.getString(
133                                         R.string.failed_to_open_app_settings_toast,
134                                         mImi.loadLabel(
135                                                 mFragment.getActivity().getPackageManager()));
136                                 Toast.makeText(
137                                         mFragment.getActivity(), msg, Toast.LENGTH_LONG).show();
138                             }
139                         }
140                     });
141         }
142         if (hasSubtypes) {
143             final OnLongClickListener listener = new OnLongClickListener() {
144                 @Override
145                 public boolean onLongClick(View arg0) {
146                     final Bundle bundle = new Bundle();
147                     bundle.putString(Settings.EXTRA_INPUT_METHOD_ID, imiId);
148                     startFragment(mFragment, InputMethodAndSubtypeEnabler.class.getName(),
149                             0, bundle);
150                     return true;
151                 }
152             };
153             mInputMethodSettingsButton.setOnLongClickListener(listener);
154         }
155         if (mSettingsIntent == null) {
156             mInputMethodSettingsButton.setVisibility(View.GONE);
157         } else {
158             updatePreferenceViews();
159         }
160     }
161 
162     @Override
setEnabled(boolean enabled)163     public void setEnabled(boolean enabled) {
164         super.setEnabled(enabled);
165         updatePreferenceViews();
166     }
167 
updatePreferenceViews()168     private void updatePreferenceViews() {
169         final boolean checked = isChecked();
170         if (mInputMethodSettingsButton != null) {
171             mInputMethodSettingsButton.setEnabled(checked);
172             mInputMethodSettingsButton.setClickable(checked);
173             mInputMethodSettingsButton.setFocusable(checked);
174             if (!checked) {
175                 mInputMethodSettingsButton.setAlpha(DISABLED_ALPHA);
176             }
177         }
178         if (mTitleText != null) {
179             mTitleText.setEnabled(true);
180         }
181         if (mSummaryText != null) {
182             mSummaryText.setEnabled(checked);
183         }
184         if (mInputMethodPref != null) {
185             mInputMethodPref.setEnabled(true);
186             mInputMethodPref.setLongClickable(checked);
187             final boolean enabled = isEnabled();
188             mInputMethodPref.setOnClickListener(enabled ? mPrefOnclickListener : null);
189             if (!enabled) {
190                 mInputMethodPref.setBackgroundColor(0);
191             }
192         }
193     }
194 
startFragment( Fragment fragment, String fragmentClass, int requestCode, Bundle extras)195     public static boolean startFragment(
196             Fragment fragment, String fragmentClass, int requestCode, Bundle extras) {
197         if (fragment.getActivity() instanceof PreferenceActivity) {
198             PreferenceActivity preferenceActivity = (PreferenceActivity)fragment.getActivity();
199             preferenceActivity.startPreferencePanel(fragmentClass, extras, 0, null, fragment,
200                     requestCode);
201             return true;
202         } else {
203             Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
204                     + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
205                     + ")");
206             return false;
207         }
208     }
209 
getSummaryString()210     public String getSummaryString() {
211         final StringBuilder builder = new StringBuilder();
212         final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(mImi, true);
213         for (InputMethodSubtype subtype : subtypes) {
214             if (builder.length() > 0) {
215                 builder.append(", ");
216             }
217             final CharSequence subtypeLabel = subtype.getDisplayName(mFragment.getActivity(),
218                     mImi.getPackageName(), mImi.getServiceInfo().applicationInfo);
219             builder.append(subtypeLabel);
220         }
221         return builder.toString();
222     }
223 
updateSummary()224     public void updateSummary() {
225         final String summary = getSummaryString();
226         if (TextUtils.isEmpty(summary)) {
227             return;
228         }
229         setSummary(summary);
230     }
231 
232     /**
233      * Sets the checkbox state and optionally saves the settings.
234      * @param checked whether to check the box
235      * @param save whether to save IME settings
236      */
setChecked(boolean checked, boolean save)237     public void setChecked(boolean checked, boolean save) {
238         super.setChecked(checked);
239         if (save) {
240             saveImeSettings();
241         }
242         updateSummary();
243     }
244 
245     @Override
setChecked(boolean checked)246     public void setChecked(boolean checked) {
247         setChecked(checked, false);
248     }
249 
showSecurityWarnDialog(InputMethodInfo imi, final InputMethodPreference chkPref)250     private void showSecurityWarnDialog(InputMethodInfo imi, final InputMethodPreference chkPref) {
251         if (mDialog != null && mDialog.isShowing()) {
252             mDialog.dismiss();
253         }
254         mDialog = (new AlertDialog.Builder(mFragment.getActivity()))
255                 .setTitle(android.R.string.dialog_alert_title)
256                 .setIconAttribute(android.R.attr.alertDialogIcon)
257                 .setCancelable(true)
258                 .setPositiveButton(android.R.string.ok,
259                         new DialogInterface.OnClickListener() {
260                     @Override
261                     public void onClick(DialogInterface dialog, int which) {
262                         chkPref.setChecked(true, true);
263                     }
264                 })
265                 .setNegativeButton(android.R.string.cancel,
266                         new DialogInterface.OnClickListener() {
267                     @Override
268                     public void onClick(DialogInterface dialog, int which) {
269                     }
270                 })
271                 .create();
272         mDialog.setMessage(mFragment.getResources().getString(R.string.ime_security_warning,
273                 imi.getServiceInfo().applicationInfo.loadLabel(
274                         mFragment.getActivity().getPackageManager())));
275         mDialog.show();
276     }
277 
278     @Override
compare(InputMethodPreference arg0, InputMethodPreference arg1)279     public int compare(InputMethodPreference arg0, InputMethodPreference arg1) {
280         if (arg0.isEnabled() == arg0.isEnabled()) {
281             return arg0.mImi.getId().compareTo(arg1.mImi.getId());
282         } else {
283             // Prefer system IMEs
284             return arg0.isEnabled() ? 1 : -1;
285         }
286     }
287 
saveImeSettings()288     private void saveImeSettings() {
289         InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(
290                 mFragment, mFragment.getActivity().getContentResolver(), mImm.getInputMethodList(),
291                 mFragment.getResources().getConfiguration().keyboard
292                         == Configuration.KEYBOARD_QWERTY);
293     }
294 }
295