• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.launcher3.compat;
2 
3 import android.content.Context;
4 import android.icu.text.AlphabeticIndex;
5 import android.os.LocaleList;
6 import android.util.Log;
7 
8 import androidx.annotation.NonNull;
9 
10 import com.android.launcher3.Utilities;
11 
12 import java.util.Locale;
13 
14 public class AlphabeticIndexCompat {
15 
16     // TODO(b/336947811): Set to false after root causing is done.
17     private static final boolean DEBUG = true;
18     private static final String TAG = "AlphabeticIndexCompat";
19     private static final String MID_DOT = "\u2219";
20     private final String mDefaultMiscLabel;
21 
22     private final AlphabeticIndex.ImmutableIndex mBaseIndex;
23 
AlphabeticIndexCompat(Context context)24     public AlphabeticIndexCompat(Context context) {
25         this(context.getResources().getConfiguration().getLocales());
26     }
27 
AlphabeticIndexCompat(LocaleList locales)28     public AlphabeticIndexCompat(LocaleList locales) {
29         int localeCount = locales.size();
30 
31         Locale primaryLocale = localeCount == 0 ? Locale.ENGLISH : locales.get(0);
32         AlphabeticIndex indexBuilder = new AlphabeticIndex(primaryLocale);
33         for (int i = 1; i < localeCount; i++) {
34             indexBuilder.addLabels(locales.get(i));
35         }
36         indexBuilder.addLabels(Locale.ENGLISH);
37         mBaseIndex = indexBuilder.buildImmutableIndex();
38 
39         if (primaryLocale.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
40             // Japanese character 他 ("misc")
41             mDefaultMiscLabel = "\u4ed6";
42             // TODO(winsonc, omakoto): We need to handle Japanese sections better,
43             // especially the kanji
44         } else {
45             // Dot
46             mDefaultMiscLabel = MID_DOT;
47         }
48     }
49 
50     /**
51      * Computes the section name for an given string {@param s}.
52      */
computeSectionName(@onNull CharSequence cs)53     public String computeSectionName(@NonNull CharSequence cs) {
54         String s = Utilities.trim(cs);
55         String sectionName = mBaseIndex.getBucket(mBaseIndex.getBucketIndex(s)).getLabel();
56         if (DEBUG) {
57             Log.d(TAG, "computeSectionName: cs: " + cs + " sectionName: " + sectionName);
58         }
59         if (Utilities.trim(sectionName).isEmpty() && s.length() > 0) {
60             int c = s.codePointAt(0);
61             boolean startsWithDigit = Character.isDigit(c);
62             if (startsWithDigit) {
63                 // Digit section
64                 return "#";
65             } else {
66                 boolean startsWithLetter = Character.isLetter(c);
67                 if (startsWithLetter) {
68                     return mDefaultMiscLabel;
69                 } else {
70                     // In languages where these differ, this ensures that we differentiate
71                     // between the misc section in the native language and a misc section
72                     // for everything else.
73                     return MID_DOT;
74                 }
75             }
76         }
77         return sectionName;
78     }
79 }
80