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 android.app.AlertDialog; 20import android.content.Context; 21import android.content.DialogInterface; 22import android.content.pm.ApplicationInfo; 23import android.os.Bundle; 24import android.preference.Preference; 25import android.preference.Preference.OnPreferenceClickListener; 26import android.preference.PreferenceScreen; 27import android.util.Log; 28import android.view.textservice.SpellCheckerInfo; 29import android.view.textservice.SpellCheckerSubtype; 30import android.view.textservice.TextServicesManager; 31import android.widget.Switch; 32 33import com.android.internal.logging.MetricsLogger; 34import com.android.settings.R; 35import com.android.settings.SettingsActivity; 36import com.android.settings.SettingsPreferenceFragment; 37import com.android.settings.inputmethod.SpellCheckerPreference.OnRadioButtonPreferenceListener; 38import com.android.settings.widget.SwitchBar; 39import com.android.settings.widget.SwitchBar.OnSwitchChangeListener; 40 41public class SpellCheckersSettings extends SettingsPreferenceFragment 42 implements OnSwitchChangeListener, OnPreferenceClickListener, 43 OnRadioButtonPreferenceListener { 44 private static final String TAG = SpellCheckersSettings.class.getSimpleName(); 45 private static final boolean DBG = false; 46 47 private static final String KEY_SPELL_CHECKER_LANGUAGE = "spellchecker_language"; 48 private static final int ITEM_ID_USE_SYSTEM_LANGUAGE = 0; 49 50 private SwitchBar mSwitchBar; 51 private Preference mSpellCheckerLanaguagePref; 52 private AlertDialog mDialog = null; 53 private SpellCheckerInfo mCurrentSci; 54 private SpellCheckerInfo[] mEnabledScis; 55 private TextServicesManager mTsm; 56 57 @Override 58 protected int getMetricsCategory() { 59 return MetricsLogger.INPUTMETHOD_SPELL_CHECKERS; 60 } 61 62 @Override 63 public void onCreate(final Bundle icicle) { 64 super.onCreate(icicle); 65 66 addPreferencesFromResource(R.xml.spellchecker_prefs); 67 mSpellCheckerLanaguagePref = findPreference(KEY_SPELL_CHECKER_LANGUAGE); 68 mSpellCheckerLanaguagePref.setOnPreferenceClickListener(this); 69 70 mTsm = (TextServicesManager) getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); 71 mCurrentSci = mTsm.getCurrentSpellChecker(); 72 mEnabledScis = mTsm.getEnabledSpellCheckers(); 73 populatePreferenceScreen(); 74 } 75 76 private void populatePreferenceScreen() { 77 final PreferenceScreen screen = getPreferenceScreen(); 78 final Context context = getActivity(); 79 final int count = (mEnabledScis == null) ? 0 : mEnabledScis.length; 80 for (int index = 0; index < count; ++index) { 81 final SpellCheckerInfo sci = mEnabledScis[index]; 82 final SpellCheckerPreference pref = new SpellCheckerPreference(context, sci, this); 83 screen.addPreference(pref); 84 InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref); 85 } 86 } 87 88 @Override 89 public void onResume() { 90 super.onResume(); 91 mSwitchBar = ((SettingsActivity)getActivity()).getSwitchBar(); 92 mSwitchBar.show(); 93 mSwitchBar.addOnSwitchChangeListener(this); 94 updatePreferenceScreen(); 95 } 96 97 @Override 98 public void onPause() { 99 super.onPause(); 100 mSwitchBar.removeOnSwitchChangeListener(this); 101 } 102 103 @Override 104 public void onSwitchChanged(final Switch switchView, final boolean isChecked) { 105 mTsm.setSpellCheckerEnabled(isChecked); 106 updatePreferenceScreen(); 107 } 108 109 private void updatePreferenceScreen() { 110 mCurrentSci = mTsm.getCurrentSpellChecker(); 111 final boolean isSpellCheckerEnabled = mTsm.isSpellCheckerEnabled(); 112 mSwitchBar.setChecked(isSpellCheckerEnabled); 113 114 final SpellCheckerSubtype currentScs = mTsm.getCurrentSpellCheckerSubtype( 115 false /* allowImplicitlySelectedSubtype */); 116 mSpellCheckerLanaguagePref.setSummary(getSpellCheckerSubtypeLabel(mCurrentSci, currentScs)); 117 118 final PreferenceScreen screen = getPreferenceScreen(); 119 final int count = screen.getPreferenceCount(); 120 for (int index = 0; index < count; index++) { 121 final Preference preference = screen.getPreference(index); 122 preference.setEnabled(isSpellCheckerEnabled); 123 if (preference instanceof SpellCheckerPreference) { 124 final SpellCheckerPreference pref = (SpellCheckerPreference)preference; 125 final SpellCheckerInfo sci = pref.getSpellCheckerInfo(); 126 pref.setSelected(mCurrentSci != null && mCurrentSci.getId().equals(sci.getId())); 127 } 128 } 129 } 130 131 private CharSequence getSpellCheckerSubtypeLabel(final SpellCheckerInfo sci, 132 final SpellCheckerSubtype subtype) { 133 if (sci == null) { 134 return null; 135 } 136 if (subtype == null) { 137 return getString(R.string.use_system_language_to_select_input_method_subtypes); 138 } 139 return subtype.getDisplayName( 140 getActivity(), sci.getPackageName(), sci.getServiceInfo().applicationInfo); 141 } 142 143 @Override 144 public boolean onPreferenceClick(final Preference pref) { 145 if (pref == mSpellCheckerLanaguagePref) { 146 showChooseLanguageDialog(); 147 return true; 148 } 149 return false; 150 } 151 152 @Override 153 public void onRadioButtonClicked(final SpellCheckerPreference pref) { 154 final SpellCheckerInfo sci = pref.getSpellCheckerInfo(); 155 final boolean isSystemApp = 156 (sci.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; 157 if (isSystemApp) { 158 changeCurrentSpellChecker(sci); 159 } else { 160 showSecurityWarnDialog(pref); 161 } 162 } 163 164 private static int convertSubtypeIndexToDialogItemId(final int index) { return index + 1; } 165 private static int convertDialogItemIdToSubtypeIndex(final int item) { return item - 1; } 166 167 private void showChooseLanguageDialog() { 168 if (mDialog != null && mDialog.isShowing()) { 169 mDialog.dismiss(); 170 } 171 final SpellCheckerInfo currentSci = mTsm.getCurrentSpellChecker(); 172 final SpellCheckerSubtype currentScs = mTsm.getCurrentSpellCheckerSubtype( 173 false /* allowImplicitlySelectedSubtype */); 174 final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 175 builder.setTitle(R.string.phone_language); 176 final int subtypeCount = currentSci.getSubtypeCount(); 177 final CharSequence[] items = new CharSequence[subtypeCount + 1 /* default */ ]; 178 items[ITEM_ID_USE_SYSTEM_LANGUAGE] = getSpellCheckerSubtypeLabel(currentSci, null); 179 int checkedItemId = ITEM_ID_USE_SYSTEM_LANGUAGE; 180 for (int index = 0; index < subtypeCount; ++index) { 181 final SpellCheckerSubtype subtype = currentSci.getSubtypeAt(index); 182 final int itemId = convertSubtypeIndexToDialogItemId(index); 183 items[itemId] = getSpellCheckerSubtypeLabel(currentSci, subtype); 184 if (subtype.equals(currentScs)) { 185 checkedItemId = itemId; 186 } 187 } 188 builder.setSingleChoiceItems(items, checkedItemId, new AlertDialog.OnClickListener() { 189 @Override 190 public void onClick(final DialogInterface dialog, final int item) { 191 if (item == ITEM_ID_USE_SYSTEM_LANGUAGE) { 192 mTsm.setSpellCheckerSubtype(null); 193 } else { 194 final int index = convertDialogItemIdToSubtypeIndex(item); 195 mTsm.setSpellCheckerSubtype(currentSci.getSubtypeAt(index)); 196 } 197 if (DBG) { 198 final SpellCheckerSubtype subtype = mTsm.getCurrentSpellCheckerSubtype( 199 true /* allowImplicitlySelectedSubtype */); 200 Log.d(TAG, "Current spell check locale is " 201 + subtype == null ? "null" : subtype.getLocale()); 202 } 203 dialog.dismiss(); 204 updatePreferenceScreen(); 205 } 206 }); 207 mDialog = builder.create(); 208 mDialog.show(); 209 } 210 211 private void showSecurityWarnDialog(final SpellCheckerPreference pref) { 212 if (mDialog != null && mDialog.isShowing()) { 213 mDialog.dismiss(); 214 } 215 final SpellCheckerInfo sci = pref.getSpellCheckerInfo(); 216 final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 217 builder.setTitle(android.R.string.dialog_alert_title); 218 builder.setMessage(getString(R.string.spellchecker_security_warning, pref.getTitle())); 219 builder.setCancelable(true); 220 builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 221 @Override 222 public void onClick(final DialogInterface dialog, final int which) { 223 changeCurrentSpellChecker(sci); 224 } 225 }); 226 builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 227 @Override 228 public void onClick(final DialogInterface dialog, final int which) { 229 } 230 }); 231 mDialog = builder.create(); 232 mDialog.show(); 233 } 234 235 private void changeCurrentSpellChecker(final SpellCheckerInfo sci) { 236 mTsm.setCurrentSpellChecker(sci); 237 if (DBG) { 238 Log.d(TAG, "Current spell check is " + mTsm.getCurrentSpellChecker().getId()); 239 } 240 updatePreferenceScreen(); 241 } 242} 243