• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LocaleEntry(String label, Locale locale)62         public LocaleEntry(String label, Locale locale) {
63             this.mLabel = label;
64             this.mLocale = locale;
65         }
66 
67         @Override
toString()68         public String toString() {
69             return this.mLabel;
70         }
71 
72         @Override
compareTo(Object o)73         public int compareTo(Object o) {
74             return sCollator.compare(this.mLabel, ((LocaleEntry) o).mLabel);
75         }
76     }
77 
78     @Override
onCreate(Bundle icicle)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 
isLocaleIn(Locale locale, String[] list)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 
hasDictionaryOrLayout(Locale locale)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 
get5Code(Locale locale)182     private String get5Code(Locale locale) {
183         String country = locale.getCountry();
184         return locale.getLanguage()
185                 + (TextUtils.isEmpty(country) ? "" : "_" + country);
186     }
187 
188     @Override
onResume()189     protected void onResume() {
190         super.onResume();
191     }
192 
193     @Override
onPause()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 
getUniqueLocales()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