Home | History | Annotate | Download | only in inputmethod
      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.support.v7.preference.Preference;
     25 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
     26 import android.support.v7.preference.Preference.OnPreferenceClickListener;
     27 import android.support.v7.preference.PreferenceScreen;
     28 import android.util.Log;
     29 import android.view.textservice.SpellCheckerInfo;
     30 import android.view.textservice.SpellCheckerSubtype;
     31 import android.view.textservice.TextServicesManager;
     32 import android.widget.Switch;
     33 
     34 import com.android.internal.logging.MetricsProto.MetricsEvent;
     35 import com.android.settings.R;
     36 import com.android.settings.SettingsActivity;
     37 import com.android.settings.SettingsPreferenceFragment;
     38 import com.android.settings.widget.SwitchBar;
     39 import com.android.settings.widget.SwitchBar.OnSwitchChangeListener;
     40 
     41 public class SpellCheckersSettings extends SettingsPreferenceFragment
     42         implements OnSwitchChangeListener, OnPreferenceClickListener, OnPreferenceChangeListener {
     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 String KEY_DEFAULT_SPELL_CHECKER = "default_spellchecker";
     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 MetricsEvent.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 SpellCheckerPreference pref = new SpellCheckerPreference(getPrefContext(),
     78                 mEnabledScis);
     79         pref.setTitle(R.string.default_spell_checker);
     80         final int count = (mEnabledScis == null) ? 0 : mEnabledScis.length;
     81         if (count > 0) {
     82             pref.setSummary("%s");
     83         } else {
     84             pref.setSummary(R.string.spell_checker_not_selected);
     85         }
     86         pref.setKey(KEY_DEFAULT_SPELL_CHECKER);
     87         pref.setOnPreferenceChangeListener(this);
     88         getPreferenceScreen().addPreference(pref);
     89     }
     90 
     91     @Override
     92     public void onResume() {
     93         super.onResume();
     94         mSwitchBar = ((SettingsActivity)getActivity()).getSwitchBar();
     95         mSwitchBar.show();
     96         mSwitchBar.addOnSwitchChangeListener(this);
     97         updatePreferenceScreen();
     98     }
     99 
    100     @Override
    101     public void onPause() {
    102         super.onPause();
    103         mSwitchBar.removeOnSwitchChangeListener(this);
    104     }
    105 
    106     @Override
    107     public void onSwitchChanged(final Switch switchView, final boolean isChecked) {
    108         mTsm.setSpellCheckerEnabled(isChecked);
    109         updatePreferenceScreen();
    110     }
    111 
    112     private void updatePreferenceScreen() {
    113         mCurrentSci = mTsm.getCurrentSpellChecker();
    114         final boolean isSpellCheckerEnabled = mTsm.isSpellCheckerEnabled();
    115         mSwitchBar.setChecked(isSpellCheckerEnabled);
    116 
    117         final SpellCheckerSubtype currentScs;
    118         if (mCurrentSci != null) {
    119             currentScs = mTsm.getCurrentSpellCheckerSubtype(
    120                     false /* allowImplicitlySelectedSubtype */);
    121         } else {
    122             currentScs = null;
    123         }
    124         mSpellCheckerLanaguagePref.setSummary(getSpellCheckerSubtypeLabel(mCurrentSci, currentScs));
    125 
    126         final PreferenceScreen screen = getPreferenceScreen();
    127         final int count = screen.getPreferenceCount();
    128         for (int index = 0; index < count; index++) {
    129             final Preference preference = screen.getPreference(index);
    130             preference.setEnabled(isSpellCheckerEnabled);
    131             if (preference instanceof SpellCheckerPreference) {
    132                 final SpellCheckerPreference pref = (SpellCheckerPreference)preference;
    133                 pref.setSelected(mCurrentSci);
    134             }
    135         }
    136         mSpellCheckerLanaguagePref.setEnabled(isSpellCheckerEnabled && mCurrentSci != null);
    137     }
    138 
    139     private CharSequence getSpellCheckerSubtypeLabel(final SpellCheckerInfo sci,
    140             final SpellCheckerSubtype subtype) {
    141         if (sci == null) {
    142             return getString(R.string.spell_checker_not_selected);
    143         }
    144         if (subtype == null) {
    145             return getString(R.string.use_system_language_to_select_input_method_subtypes);
    146         }
    147         return subtype.getDisplayName(
    148                 getActivity(), sci.getPackageName(), sci.getServiceInfo().applicationInfo);
    149     }
    150 
    151     @Override
    152     public boolean onPreferenceClick(final Preference pref) {
    153         if (pref == mSpellCheckerLanaguagePref) {
    154             showChooseLanguageDialog();
    155             return true;
    156         }
    157         return false;
    158     }
    159 
    160     @Override
    161     public boolean onPreferenceChange(Preference preference, Object newValue) {
    162         final SpellCheckerInfo sci = (SpellCheckerInfo) newValue;
    163         final boolean isSystemApp =
    164                 (sci.getServiceInfo().applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
    165         if (isSystemApp) {
    166             changeCurrentSpellChecker(sci);
    167             return true;
    168         } else {
    169             showSecurityWarnDialog(sci);
    170             return false;
    171         }
    172     }
    173 
    174     private static int convertSubtypeIndexToDialogItemId(final int index) { return index + 1; }
    175     private static int convertDialogItemIdToSubtypeIndex(final int item) { return item - 1; }
    176 
    177     private void showChooseLanguageDialog() {
    178         if (mDialog != null && mDialog.isShowing()) {
    179             mDialog.dismiss();
    180         }
    181         final SpellCheckerInfo currentSci = mTsm.getCurrentSpellChecker();
    182         if (currentSci == null) {
    183             // This can happen in some situations.  One example is that the package that the current
    184             // spell checker belongs to was uninstalled or being in background.
    185             return;
    186         }
    187         final SpellCheckerSubtype currentScs = mTsm.getCurrentSpellCheckerSubtype(
    188                 false /* allowImplicitlySelectedSubtype */);
    189         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    190         builder.setTitle(R.string.phone_language);
    191         final int subtypeCount = currentSci.getSubtypeCount();
    192         final CharSequence[] items = new CharSequence[subtypeCount + 1 /* default */ ];
    193         items[ITEM_ID_USE_SYSTEM_LANGUAGE] = getSpellCheckerSubtypeLabel(currentSci, null);
    194         int checkedItemId = ITEM_ID_USE_SYSTEM_LANGUAGE;
    195         for (int index = 0; index < subtypeCount; ++index) {
    196             final SpellCheckerSubtype subtype = currentSci.getSubtypeAt(index);
    197             final int itemId = convertSubtypeIndexToDialogItemId(index);
    198             items[itemId] = getSpellCheckerSubtypeLabel(currentSci, subtype);
    199             if (subtype.equals(currentScs)) {
    200                 checkedItemId = itemId;
    201             }
    202         }
    203         builder.setSingleChoiceItems(items, checkedItemId, new AlertDialog.OnClickListener() {
    204             @Override
    205             public void onClick(final DialogInterface dialog, final int item) {
    206                 if (item == ITEM_ID_USE_SYSTEM_LANGUAGE) {
    207                     mTsm.setSpellCheckerSubtype(null);
    208                 } else {
    209                     final int index = convertDialogItemIdToSubtypeIndex(item);
    210                     mTsm.setSpellCheckerSubtype(currentSci.getSubtypeAt(index));
    211                 }
    212                 if (DBG) {
    213                     final SpellCheckerSubtype subtype = mTsm.getCurrentSpellCheckerSubtype(
    214                             true /* allowImplicitlySelectedSubtype */);
    215                     Log.d(TAG, "Current spell check locale is "
    216                             + subtype == null ? "null" : subtype.getLocale());
    217                 }
    218                 dialog.dismiss();
    219                 updatePreferenceScreen();
    220             }
    221         });
    222         mDialog = builder.create();
    223         mDialog.show();
    224     }
    225 
    226     private void showSecurityWarnDialog(final SpellCheckerInfo sci) {
    227         if (mDialog != null && mDialog.isShowing()) {
    228             mDialog.dismiss();
    229         }
    230         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    231         builder.setTitle(android.R.string.dialog_alert_title);
    232         builder.setMessage(getString(R.string.spellchecker_security_warning,
    233                 sci.loadLabel(getPackageManager())));
    234         builder.setCancelable(true);
    235         builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
    236             @Override
    237             public void onClick(final DialogInterface dialog, final int which) {
    238                 changeCurrentSpellChecker(sci);
    239             }
    240         });
    241         builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
    242             @Override
    243             public void onClick(final DialogInterface dialog, final int which) {
    244             }
    245         });
    246         mDialog = builder.create();
    247         mDialog.show();
    248     }
    249 
    250     private void changeCurrentSpellChecker(final SpellCheckerInfo sci) {
    251         mTsm.setCurrentSpellChecker(sci);
    252         if (DBG) {
    253             Log.d(TAG, "Current spell check is " + mTsm.getCurrentSpellChecker().getId());
    254         }
    255         updatePreferenceScreen();
    256     }
    257 }
    258