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