1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.launcher3.model; 17 18 import android.content.Context; 19 20 import com.android.launcher3.AppInfo; 21 import com.android.launcher3.ItemInfo; 22 import com.android.launcher3.util.Thunk; 23 24 import java.text.Collator; 25 import java.util.Comparator; 26 27 /** 28 * Class to manage access to an app name comparator. 29 * <p> 30 * Used to sort application name in all apps view and widget tray view. 31 */ 32 public class AppNameComparator { 33 private final Collator mCollator; 34 private final AbstractUserComparator<ItemInfo> mAppInfoComparator; 35 private final Comparator<String> mSectionNameComparator; 36 AppNameComparator(Context context)37 public AppNameComparator(Context context) { 38 mCollator = Collator.getInstance(); 39 mAppInfoComparator = new AbstractUserComparator<ItemInfo>(context) { 40 41 @Override 42 public final int compare(ItemInfo a, ItemInfo b) { 43 // Order by the title in the current locale 44 int result = compareTitles(a.title.toString(), b.title.toString()); 45 if (result == 0 && a instanceof AppInfo && b instanceof AppInfo) { 46 AppInfo aAppInfo = (AppInfo) a; 47 AppInfo bAppInfo = (AppInfo) b; 48 // If two apps have the same title, then order by the component name 49 result = aAppInfo.componentName.compareTo(bAppInfo.componentName); 50 if (result == 0) { 51 // If the two apps are the same component, then prioritize by the order that 52 // the app user was created (prioritizing the main user's apps) 53 return super.compare(a, b); 54 } 55 } 56 return result; 57 } 58 }; 59 mSectionNameComparator = new Comparator<String>() { 60 @Override 61 public int compare(String o1, String o2) { 62 return compareTitles(o1, o2); 63 } 64 }; 65 } 66 67 /** 68 * Returns a locale-aware comparator that will alphabetically order a list of applications. 69 */ getAppInfoComparator()70 public Comparator<ItemInfo> getAppInfoComparator() { 71 return mAppInfoComparator; 72 } 73 74 /** 75 * Returns a locale-aware comparator that will alphabetically order a list of section names. 76 */ getSectionNameComparator()77 public Comparator<String> getSectionNameComparator() { 78 return mSectionNameComparator; 79 } 80 81 /** 82 * Compares two titles with the same return value semantics as Comparator. 83 */ compareTitles(String titleA, String titleB)84 @Thunk int compareTitles(String titleA, String titleB) { 85 // Ensure that we de-prioritize any titles that don't start with a linguistic letter or digit 86 boolean aStartsWithLetter = (titleA.length() > 0) && 87 Character.isLetterOrDigit(titleA.codePointAt(0)); 88 boolean bStartsWithLetter = (titleB.length() > 0) && 89 Character.isLetterOrDigit(titleB.codePointAt(0)); 90 if (aStartsWithLetter && !bStartsWithLetter) { 91 return -1; 92 } else if (!aStartsWithLetter && bStartsWithLetter) { 93 return 1; 94 } 95 96 // Order by the title in the current locale 97 return mCollator.compare(titleA, titleB); 98 } 99 } 100