OSDN Git Service

resolved conflicts for merge of 13ef17a3 to mnc-dr-dev
[android-x86/packages-apps-Launcher3.git] / src / com / android / launcher3 / compat / AlphabeticIndexCompat.java
1 package com.android.launcher3.compat;
2
3 import android.content.Context;
4 import com.android.launcher3.Utilities;
5
6 import java.lang.reflect.Constructor;
7 import java.lang.reflect.Method;
8 import java.util.Locale;
9
10 /**
11  * Fallback class to support Alphabetic indexing if not supported by the framework.
12  * TODO(winsonc): disable for non-english locales
13  */
14 class BaseAlphabeticIndex {
15
16     private static final String BUCKETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-";
17     private static final int UNKNOWN_BUCKET_INDEX = BUCKETS.length() - 1;
18
19     public BaseAlphabeticIndex() {}
20
21     /**
22      * Sets the max number of the label buckets in this index.
23      */
24     public void setMaxLabelCount(int count) {
25         // Not currently supported
26     }
27
28     /**
29      * Returns the index of the bucket in which the given string should appear.
30      */
31     protected int getBucketIndex(String s) {
32         if (s.isEmpty()) {
33             return UNKNOWN_BUCKET_INDEX;
34         }
35         int index = BUCKETS.indexOf(s.substring(0, 1).toUpperCase());
36         if (index != -1) {
37             return index;
38         }
39         return UNKNOWN_BUCKET_INDEX;
40     }
41
42     /**
43      * Returns the label for the bucket at the given index (as returned by getBucketIndex).
44      */
45     protected String getBucketLabel(int index) {
46         return BUCKETS.substring(index, index + 1);
47     }
48 }
49
50 /**
51  * Reflected libcore.icu.AlphabeticIndex implementation, falls back to the base alphabetic index.
52  */
53 public class AlphabeticIndexCompat extends BaseAlphabeticIndex {
54
55     private static final String MID_DOT = "\u2219";
56
57     private Object mAlphabeticIndex;
58     private Method mAddLabelsMethod;
59     private Method mSetMaxLabelCountMethod;
60     private Method mGetBucketIndexMethod;
61     private Method mGetBucketLabelMethod;
62     private boolean mHasValidAlphabeticIndex;
63     private String mDefaultMiscLabel;
64
65     public AlphabeticIndexCompat(Context context) {
66         super();
67         try {
68             Locale curLocale = context.getResources().getConfiguration().locale;
69             Class clazz = Class.forName("libcore.icu.AlphabeticIndex");
70             Constructor ctor = clazz.getConstructor(Locale.class);
71             mAddLabelsMethod = clazz.getDeclaredMethod("addLabels", Locale.class);
72             mSetMaxLabelCountMethod = clazz.getDeclaredMethod("setMaxLabelCount", int.class);
73             mGetBucketIndexMethod = clazz.getDeclaredMethod("getBucketIndex", String.class);
74             mGetBucketLabelMethod = clazz.getDeclaredMethod("getBucketLabel", int.class);
75             mAlphabeticIndex = ctor.newInstance(curLocale);
76             try {
77                 // Ensure we always have some base English locale buckets
78                 if (!curLocale.getLanguage().equals(Locale.ENGLISH.getLanguage())) {
79                     mAddLabelsMethod.invoke(mAlphabeticIndex, Locale.ENGLISH);
80                 }
81             } catch (Exception e) {
82                 e.printStackTrace();
83             }
84             if (curLocale.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
85                 // Japanese character 他 ("misc")
86                 mDefaultMiscLabel = "\u4ed6";
87                 // TODO(winsonc, omakoto): We need to handle Japanese sections better, especially the kanji
88             } else {
89                 // Dot
90                 mDefaultMiscLabel = MID_DOT;
91             }
92             mHasValidAlphabeticIndex = true;
93         } catch (Exception e) {
94             mHasValidAlphabeticIndex = false;
95         }
96     }
97
98     /**
99      * Sets the max number of the label buckets in this index.
100      * (ICU 51 default is 99)
101      */
102     public void setMaxLabelCount(int count) {
103         if (mHasValidAlphabeticIndex) {
104             try {
105                 mSetMaxLabelCountMethod.invoke(mAlphabeticIndex, count);
106             } catch (Exception e) {
107                 e.printStackTrace();
108             }
109         } else {
110             super.setMaxLabelCount(count);
111         }
112     }
113
114     /**
115      * Computes the section name for an given string {@param s}.
116      */
117     public String computeSectionName(CharSequence cs) {
118         String s = Utilities.trim(cs);
119         String sectionName = getBucketLabel(getBucketIndex(s));
120         if (Utilities.trim(sectionName).isEmpty() && s.length() > 0) {
121             int c = s.codePointAt(0);
122             boolean startsWithDigit = Character.isDigit(c);
123             if (startsWithDigit) {
124                 // Digit section
125                 return "#";
126             } else {
127                 boolean startsWithLetter = Character.isLetter(c);
128                 if (startsWithLetter) {
129                     return mDefaultMiscLabel;
130                 } else {
131                     // In languages where these differ, this ensures that we differentiate
132                     // between the misc section in the native language and a misc section
133                     // for everything else.
134                     return MID_DOT;
135                 }
136             }
137         }
138         return sectionName;
139     }
140
141     /**
142      * Returns the index of the bucket in which {@param s} should appear.
143      * Function is synchronized because underlying routine walks an iterator
144      * whose state is maintained inside the index object.
145      */
146     protected int getBucketIndex(String s) {
147         if (mHasValidAlphabeticIndex) {
148             try {
149                 return (Integer) mGetBucketIndexMethod.invoke(mAlphabeticIndex, s);
150             } catch (Exception e) {
151                 e.printStackTrace();
152             }
153         }
154         return super.getBucketIndex(s);
155     }
156
157     /**
158      * Returns the label for the bucket at the given index (as returned by getBucketIndex).
159      */
160     protected String getBucketLabel(int index) {
161         if (mHasValidAlphabeticIndex) {
162             try {
163                 return (String) mGetBucketLabelMethod.invoke(mAlphabeticIndex, index);
164             } catch (Exception e) {
165                 e.printStackTrace();
166             }
167         }
168         return super.getBucketLabel(index);
169     }
170 }