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