Home | History | Annotate | Download | only in languageswitcher
      1 /*
      2  * Copyright (C) 2008-2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.android.inputmethod.deprecated.languageswitcher;
     18 
     19 import com.android.inputmethod.compat.SharedPreferencesCompat;
     20 import com.android.inputmethod.keyboard.internal.KeyboardBuilder;
     21 import com.android.inputmethod.latin.DictionaryFactory;
     22 import com.android.inputmethod.latin.LocaleUtils;
     23 import com.android.inputmethod.latin.R;
     24 import com.android.inputmethod.latin.Settings;
     25 import com.android.inputmethod.latin.Utils;
     26 
     27 import org.xmlpull.v1.XmlPullParserException;
     28 
     29 import android.content.SharedPreferences;
     30 import android.content.SharedPreferences.Editor;
     31 import android.content.res.Resources;
     32 import android.os.Bundle;
     33 import android.preference.CheckBoxPreference;
     34 import android.preference.PreferenceActivity;
     35 import android.preference.PreferenceGroup;
     36 import android.preference.PreferenceManager;
     37 import android.text.TextUtils;
     38 import android.util.Pair;
     39 
     40 import java.io.IOException;
     41 import java.text.Collator;
     42 import java.util.ArrayList;
     43 import java.util.Arrays;
     44 import java.util.HashMap;
     45 import java.util.Locale;
     46 import java.util.Map.Entry;
     47 import java.util.TreeMap;
     48 
     49 public class InputLanguageSelection extends PreferenceActivity {
     50 
     51     private SharedPreferences mPrefs;
     52     private String mSelectedLanguages;
     53     private HashMap<CheckBoxPreference, Locale> mLocaleMap =
     54             new HashMap<CheckBoxPreference, Locale>();
     55 
     56     private static class LocaleEntry implements Comparable<Object> {
     57         private static Collator sCollator = Collator.getInstance();
     58 
     59         private String mLabel;
     60         public final Locale mLocale;
     61 
     62         public LocaleEntry(String label, Locale locale) {
     63             this.mLabel = label;
     64             this.mLocale = locale;
     65         }
     66 
     67         @Override
     68         public String toString() {
     69             return this.mLabel;
     70         }
     71 
     72         @Override
     73         public int compareTo(Object o) {
     74             return sCollator.compare(this.mLabel, ((LocaleEntry) o).mLabel);
     75         }
     76     }
     77 
     78     @Override
     79     protected void onCreate(Bundle icicle) {
     80         super.onCreate(icicle);
     81         addPreferencesFromResource(R.xml.language_prefs);
     82         // Get the settings preferences
     83         mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
     84         mSelectedLanguages = mPrefs.getString(Settings.PREF_SELECTED_LANGUAGES, "");
     85         String[] languageList = mSelectedLanguages.split(",");
     86         ArrayList<LocaleEntry> availableLanguages = getUniqueLocales();
     87         PreferenceGroup parent = getPreferenceScreen();
     88         final HashMap<Long, LocaleEntry> dictionaryIdLocaleMap = new HashMap<Long, LocaleEntry>();
     89         final TreeMap<LocaleEntry, Boolean> localeHasDictionaryMap =
     90                 new TreeMap<LocaleEntry, Boolean>();
     91         for (int i = 0; i < availableLanguages.size(); i++) {
     92             LocaleEntry loc = availableLanguages.get(i);
     93             Locale locale = loc.mLocale;
     94             final Pair<Long, Boolean> hasDictionaryOrLayout = hasDictionaryOrLayout(locale);
     95             final Long dictionaryId = hasDictionaryOrLayout.first;
     96             final boolean hasLayout = hasDictionaryOrLayout.second;
     97             final boolean hasDictionary = dictionaryId != null;
     98             // Add this locale to the supported list if:
     99             // 1) this locale has a layout/ 2) this locale has a dictionary
    100             // If some locales have no layout but have a same dictionary, the shortest locale
    101             // will be added to the supported list.
    102             if (!hasLayout && !hasDictionary) {
    103                 continue;
    104             }
    105             if (hasLayout) {
    106                 localeHasDictionaryMap.put(loc, hasDictionary);
    107             }
    108             if (!hasDictionary) {
    109                 continue;
    110             }
    111             if (dictionaryIdLocaleMap.containsKey(dictionaryId)) {
    112                 final String newLocale = locale.toString();
    113                 final String oldLocale =
    114                         dictionaryIdLocaleMap.get(dictionaryId).mLocale.toString();
    115                 // Check if this locale is more appropriate to be the candidate of the input locale.
    116                 if (oldLocale.length() <= newLocale.length() && !hasLayout) {
    117                     // Don't add this new locale to the map<dictionary id, locale> if:
    118                     // 1) the new locale's name is longer than the existing one, and
    119                     // 2) the new locale doesn't have its layout
    120                     continue;
    121                 }
    122             }
    123             dictionaryIdLocaleMap.put(dictionaryId, loc);
    124         }
    125 
    126         for (LocaleEntry localeEntry : dictionaryIdLocaleMap.values()) {
    127             if (!localeHasDictionaryMap.containsKey(localeEntry)) {
    128                 localeHasDictionaryMap.put(localeEntry, true);
    129             }
    130         }
    131 
    132         for (Entry<LocaleEntry, Boolean> entry : localeHasDictionaryMap.entrySet()) {
    133             final LocaleEntry localeEntry = entry.getKey();
    134             final Locale locale = localeEntry.mLocale;
    135             final Boolean hasDictionary = entry.getValue();
    136             CheckBoxPreference pref = new CheckBoxPreference(this);
    137             pref.setTitle(localeEntry.mLabel);
    138             boolean checked = isLocaleIn(locale, languageList);
    139             pref.setChecked(checked);
    140             if (hasDictionary) {
    141                 pref.setSummary(R.string.has_dictionary);
    142             }
    143             mLocaleMap.put(pref, locale);
    144             parent.addPreference(pref);
    145         }
    146     }
    147 
    148     private boolean isLocaleIn(Locale locale, String[] list) {
    149         String lang = get5Code(locale);
    150         for (int i = 0; i < list.length; i++) {
    151             if (lang.equalsIgnoreCase(list[i])) return true;
    152         }
    153         return false;
    154     }
    155 
    156     private Pair<Long, Boolean> hasDictionaryOrLayout(Locale locale) {
    157         if (locale == null) return new Pair<Long, Boolean>(null, false);
    158         final Resources res = getResources();
    159         final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale);
    160         final Long dictionaryId = DictionaryFactory.getDictionaryId(this, locale);
    161         boolean hasLayout = false;
    162 
    163         try {
    164             final String localeStr = locale.toString();
    165             final String[] layoutCountryCodes = KeyboardBuilder.parseKeyboardLocale(
    166                     this, R.xml.kbd_qwerty).split(",", -1);
    167             if (!TextUtils.isEmpty(localeStr) && layoutCountryCodes.length > 0) {
    168                 for (String s : layoutCountryCodes) {
    169                     if (s.equals(localeStr)) {
    170                         hasLayout = true;
    171                         break;
    172                     }
    173                 }
    174             }
    175         } catch (XmlPullParserException e) {
    176         } catch (IOException e) {
    177         }
    178         LocaleUtils.setSystemLocale(res, saveLocale);
    179         return new Pair<Long, Boolean>(dictionaryId, hasLayout);
    180     }
    181 
    182     private String get5Code(Locale locale) {
    183         String country = locale.getCountry();
    184         return locale.getLanguage()
    185                 + (TextUtils.isEmpty(country) ? "" : "_" + country);
    186     }
    187 
    188     @Override
    189     protected void onResume() {
    190         super.onResume();
    191     }
    192 
    193     @Override
    194     protected void onPause() {
    195         super.onPause();
    196         // Save the selected languages
    197         String checkedLanguages = "";
    198         PreferenceGroup parent = getPreferenceScreen();
    199         int count = parent.getPreferenceCount();
    200         for (int i = 0; i < count; i++) {
    201             CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i);
    202             if (pref.isChecked()) {
    203                 checkedLanguages += get5Code(mLocaleMap.get(pref)) + ",";
    204             }
    205         }
    206         if (checkedLanguages.length() < 1) checkedLanguages = null; // Save null
    207         Editor editor = mPrefs.edit();
    208         editor.putString(Settings.PREF_SELECTED_LANGUAGES, checkedLanguages);
    209         SharedPreferencesCompat.apply(editor);
    210     }
    211 
    212     public ArrayList<LocaleEntry> getUniqueLocales() {
    213         String[] locales = getAssets().getLocales();
    214         Arrays.sort(locales);
    215         ArrayList<LocaleEntry> uniqueLocales = new ArrayList<LocaleEntry>();
    216 
    217         final int origSize = locales.length;
    218         LocaleEntry[] preprocess = new LocaleEntry[origSize];
    219         int finalSize = 0;
    220         for (int i = 0 ; i < origSize; i++ ) {
    221             String s = locales[i];
    222             int len = s.length();
    223             String language = "";
    224             String country = "";
    225             if (len == 5) {
    226                 language = s.substring(0, 2);
    227                 country = s.substring(3, 5);
    228             } else if (len < 5) {
    229                 language = s;
    230             }
    231             Locale l = new Locale(language, country);
    232 
    233             // Exclude languages that are not relevant to LatinIME
    234             if (TextUtils.isEmpty(language)) {
    235                 continue;
    236             }
    237 
    238             if (finalSize == 0) {
    239                 preprocess[finalSize++] =
    240                         new LocaleEntry(Utils.getFullDisplayName(l, false), l);
    241             } else {
    242                 if (s.equals("zz_ZZ")) {
    243                     // ignore this locale
    244                 } else {
    245                     final String displayName = Utils.getFullDisplayName(l, false);
    246                     preprocess[finalSize++] = new LocaleEntry(displayName, l);
    247                 }
    248             }
    249         }
    250         for (int i = 0; i < finalSize ; i++) {
    251             uniqueLocales.add(preprocess[i]);
    252         }
    253         return uniqueLocales;
    254     }
    255 }
    256