171ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard/*
271ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * Copyright (C) 2011 The Android Open Source Project
371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard *
471ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * Licensed under the Apache License, Version 2.0 (the "License");
571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * you may not use this file except in compliance with the License.
671ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * You may obtain a copy of the License at
771ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard *
871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard *      http://www.apache.org/licenses/LICENSE-2.0
971ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard *
1071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * Unless required by applicable law or agreed to in writing, software
1171ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * distributed under the License is distributed on an "AS IS" BASIS,
1271ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * See the License for the specific language governing permissions and
1471ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard * limitations under the License.
1571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard */
1671ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
1771ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardpackage com.android.settings.inputmethod;
1871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
1971ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport com.android.settings.R;
2071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport com.android.settings.SettingsPreferenceFragment;
2171ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport com.android.settings.Utils;
2271ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
2371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport android.app.Activity;
2471c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataokaimport android.content.Context;
2571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport android.content.Intent;
2671ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport android.database.Cursor;
2771ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport android.os.Bundle;
2871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport android.preference.Preference;
2971ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport android.preference.PreferenceGroup;
3071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport android.provider.UserDictionary;
3171c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataokaimport android.text.TextUtils;
3271c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataokaimport android.view.inputmethod.InputMethodInfo;
3371c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataokaimport android.view.inputmethod.InputMethodManager;
3471c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataokaimport android.view.inputmethod.InputMethodSubtype;
3571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
3671c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataokaimport java.util.List;
3771ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport java.util.Locale;
3871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardimport java.util.TreeSet;
3971ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
4071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalardpublic class UserDictionaryList extends SettingsPreferenceFragment {
414e658ba969830e8c9617dc8938271df1ed09aa44Jean Chalard    public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION =
4271ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard            "android.settings.USER_DICTIONARY_SETTINGS";
4371c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka    private String mLocale;
4471ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
4571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    @Override
4671ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    public void onCreate(Bundle icicle) {
4771ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        super.onCreate(icicle);
4871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
4971c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        getActivity().getActionBar().setTitle(R.string.user_dict_settings_title);
5071c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka    }
5171c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka
5271c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka    @Override
5371c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka    public void onActivityCreated(Bundle savedInstanceState) {
5471c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        super.onActivityCreated(savedInstanceState);
5571c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka
5671c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final Intent intent = getActivity().getIntent();
5771c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final String localeFromIntent =
5871c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka                null == intent ? null : intent.getStringExtra("locale");
5971c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka
6071c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final Bundle arguments = getArguments();
6171c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final String localeFromArguments =
6271c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka                null == arguments ? null : arguments.getString("locale");
6371c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka
6471c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final String locale;
6571c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        if (null != localeFromArguments) {
6671c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            locale = localeFromArguments;
6771c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        } else if (null != localeFromIntent) {
6871c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            locale = localeFromIntent;
6971c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        } else {
7071c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            locale = null;
7171c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        }
7271c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        mLocale = locale;
7371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    }
7471ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
75990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav    public static TreeSet<String> getUserDictionaryLocalesSet(Context context) {
76990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav        final Cursor cursor = context.getContentResolver().query(
77990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav                UserDictionary.Words.CONTENT_URI, new String[] { UserDictionary.Words.LOCALE },
7871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard                null, null, null);
7971c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final TreeSet<String> localeSet = new TreeSet<String>();
80410e75b15bd7ecfcb8985c4368fec5e355e2c099Jean Chalard        if (null == cursor) {
81410e75b15bd7ecfcb8985c4368fec5e355e2c099Jean Chalard            // The user dictionary service is not present or disabled. Return null.
82410e75b15bd7ecfcb8985c4368fec5e355e2c099Jean Chalard            return null;
8371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        }
84990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav        try {
85990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav            if (cursor.moveToFirst()) {
86990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav                final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
87990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav                do {
88990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav                    final String locale = cursor.getString(columnIndex);
89990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav                    localeSet.add(null != locale ? locale : "");
90990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav                } while (cursor.moveToNext());
91990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav            }
92990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav        } finally {
93990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav            cursor.close();
94990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav        }
95990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav
96f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        // CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings
97f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        // if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
98f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        //     // For ICS, we need to show "For all languages" in case that the keyboard locale
99f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        //     // is different from the system locale
100f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        //     localeSet.add("");
101f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        // }
102f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka
10371c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final InputMethodManager imm =
104990159abaad7f314fbe1f9eaf064a088806ffb19Svetoslav                (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
10571c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final List<InputMethodInfo> imis = imm.getEnabledInputMethodList();
106f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        for (final InputMethodInfo imi : imis) {
10771c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            final List<InputMethodSubtype> subtypes =
10871c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka                    imm.getEnabledInputMethodSubtypeList(
10971c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka                            imi, true /* allowsImplicitlySelectedSubtypes */);
11071c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            for (InputMethodSubtype subtype : subtypes) {
11171c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka                final String locale = subtype.getLocale();
11271c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka                if (!TextUtils.isEmpty(locale)) {
11371c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka                    localeSet.add(locale);
11471c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka                }
11571c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            }
11671c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        }
117f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka
118f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        // We come here after we have collected locales from existing user dictionary entries and
119f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        // enabled subtypes. If we already have the locale-without-country version of the system
120f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        // locale, we don't add the system locale to avoid confusion even though it's technically
121f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        // correct to add it.
122f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) {
123f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka            localeSet.add(Locale.getDefault().toString());
124f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka        }
125f64e3b7b925cd0cd86b2cf577e50d7884742bf1bSatoshi Kataoka
12671c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        return localeSet;
12771ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    }
12871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
12971ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    /**
13071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard     * Creates the entries that allow the user to go into the user dictionary for each locale.
13171ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard     * @param userDictGroup The group to put the settings in.
13271ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard     */
133b355683253506fbe6112ee81775caf02c1b7485cSatoshi Kataoka    protected void createUserDictSettings(PreferenceGroup userDictGroup) {
13471ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        final Activity activity = getActivity();
13571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        userDictGroup.removeAll();
13671c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        final TreeSet<String> localeSet =
137f54622e46c9164e4ab46c09c9c3ff173828d5940Jean Chalard                UserDictionaryList.getUserDictionaryLocalesSet(activity);
13871c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        if (mLocale != null) {
13971c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            // If the caller explicitly specify empty string as a locale, we'll show "all languages"
14071c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            // in the list.
14171c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            localeSet.add(mLocale);
14271c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        }
143bac2974dd025216ecfb3546a3f6c89d0d646484cSatoshi Kataoka        if (localeSet.size() > 1) {
144bac2974dd025216ecfb3546a3f6c89d0d646484cSatoshi Kataoka            // Have an "All languages" entry in the languages list if there are two or more active
145bac2974dd025216ecfb3546a3f6c89d0d646484cSatoshi Kataoka            // languages
146bac2974dd025216ecfb3546a3f6c89d0d646484cSatoshi Kataoka            localeSet.add("");
147bac2974dd025216ecfb3546a3f6c89d0d646484cSatoshi Kataoka        }
14871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
14971c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka        if (localeSet.isEmpty()) {
15071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard            userDictGroup.addPreference(createUserDictionaryPreference(null, activity));
15171ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        } else {
15271c915b67213c38875a687d42f957b6fa2fa990bSatoshi Kataoka            for (String locale : localeSet) {
15371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard                userDictGroup.addPreference(createUserDictionaryPreference(locale, activity));
15471ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard            }
15571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        }
15671ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    }
15771ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
15871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    /**
15971ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard     * Create a single User Dictionary Preference object, with its parameters set.
16071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard     * @param locale The locale for which this user dictionary is for.
16171ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard     * @return The corresponding preference.
16271ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard     */
16371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    protected Preference createUserDictionaryPreference(String locale, Activity activity) {
16471ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        final Preference newPref = new Preference(getActivity());
16571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
16671ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        if (null == locale) {
16771ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard            newPref.setTitle(Locale.getDefault().getDisplayName());
16871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        } else {
16971ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard            if ("".equals(locale))
17071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard                newPref.setTitle(getString(R.string.user_dict_settings_all_languages));
17171ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard            else
17271ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard                newPref.setTitle(Utils.createLocaleFromString(locale).getDisplayName());
17371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard            intent.putExtra("locale", locale);
17471ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard            newPref.getExtras().putString("locale", locale);
17571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        }
17671ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        newPref.setIntent(intent);
177b9f837dd1da22f41c72e0cdc1454a486dbc6c448Jean Chalard        newPref.setFragment(com.android.settings.UserDictionarySettings.class.getName());
17871ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        return newPref;
17971ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    }
18071ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard
18171ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    @Override
18271ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    public void onResume() {
18371ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard        super.onResume();
184b355683253506fbe6112ee81775caf02c1b7485cSatoshi Kataoka        createUserDictSettings(getPreferenceScreen());
18571ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard    }
18671ad1f4e3e819a40a830a148a2d1bd7b10fed09dJean Chalard}
187