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.settings.R;
34import com.android.settings.SettingsActivity;
35import com.android.settings.SettingsPreferenceFragment;
36import com.android.settings.inputmethod.SpellCheckerPreference.OnRadioButtonPreferenceListener;
37import com.android.settings.widget.SwitchBar;
38import com.android.settings.widget.SwitchBar.OnSwitchChangeListener;
39
40public 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