1 /* 2 * Copyright (C) 2021 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.widget.model; 17 18 import android.content.Context; 19 import android.content.res.Resources; 20 21 import androidx.annotation.Nullable; 22 23 import com.android.launcher3.R; 24 import com.android.launcher3.model.WidgetItem; 25 import com.android.launcher3.model.data.PackageItemInfo; 26 import com.android.launcher3.util.PluralMessageFormat; 27 28 import java.util.List; 29 import java.util.function.BiFunction; 30 import java.util.stream.Collectors; 31 32 /** An information holder for an app which has widgets or/and shortcuts. */ 33 public final class WidgetsListHeaderEntry extends WidgetsListBaseEntry { 34 35 private static final BiFunction<Context, WidgetsListHeaderEntry, String> SUBTITLE_SEARCH = 36 (context, entry) -> entry.mWidgets.stream() 37 .map(item -> item.label).sorted().collect(Collectors.joining(", ")); 38 39 @Nullable buildWidgetsCountString(Context context, int wc, int sc)40 private static String buildWidgetsCountString(Context context, int wc, int sc) { 41 Resources resources = context.getResources(); 42 if (wc == 0 && sc == 0) { 43 return null; 44 } 45 46 String subtitle; 47 if (wc > 0 && sc > 0) { 48 String widgetsCount = PluralMessageFormat.getIcuPluralString(context, 49 R.string.widgets_count, wc); 50 String shortcutsCount = PluralMessageFormat.getIcuPluralString(context, 51 R.string.shortcuts_count, sc); 52 subtitle = resources.getString(R.string.widgets_and_shortcuts_count, 53 widgetsCount, shortcutsCount); 54 } else if (wc > 0) { 55 subtitle = PluralMessageFormat.getIcuPluralString(context, 56 R.string.widgets_count, wc); 57 } else { 58 subtitle = PluralMessageFormat.getIcuPluralString(context, 59 R.string.shortcuts_count, sc); 60 } 61 return subtitle; 62 } 63 64 private final boolean mIsWidgetListShown; 65 /** Selected widgets displayed */ 66 private final int mVisibleWidgetsCount; 67 private final boolean mIsSearchEntry; 68 WidgetsListHeaderEntry(PackageItemInfo pkgItem, String titleSectionName, List<WidgetItem> items, int visibleWidgetsCount, boolean isSearchEntry, boolean isWidgetListShown)69 private WidgetsListHeaderEntry(PackageItemInfo pkgItem, String titleSectionName, 70 List<WidgetItem> items, int visibleWidgetsCount, 71 boolean isSearchEntry, boolean isWidgetListShown) { 72 super(pkgItem, titleSectionName, items); 73 mVisibleWidgetsCount = visibleWidgetsCount; 74 mIsSearchEntry = isSearchEntry; 75 mIsWidgetListShown = isWidgetListShown; 76 } 77 WidgetsListHeaderEntry(PackageItemInfo pkgItem, String titleSectionName, List<WidgetItem> items, boolean isSearchEntry, boolean isWidgetListShown)78 private WidgetsListHeaderEntry(PackageItemInfo pkgItem, String titleSectionName, 79 List<WidgetItem> items, boolean isSearchEntry, boolean isWidgetListShown) { 80 super(pkgItem, titleSectionName, items); 81 mVisibleWidgetsCount = (int) items.stream().filter(w -> w.widgetInfo != null).count(); 82 mIsSearchEntry = isSearchEntry; 83 mIsWidgetListShown = isWidgetListShown; 84 } 85 86 /** Returns {@code true} if the widgets list associated with this header is shown. */ isWidgetListShown()87 public boolean isWidgetListShown() { 88 return mIsWidgetListShown; 89 } 90 91 @Override toString()92 public String toString() { 93 return "Header:" + mPkgItem.packageName + ":" + mWidgets.size(); 94 } 95 isSearchEntry()96 public boolean isSearchEntry() { 97 return mIsSearchEntry; 98 } 99 100 @Nullable getSubtitle(Context context)101 public String getSubtitle(Context context) { 102 if (mIsSearchEntry) { 103 return SUBTITLE_SEARCH.apply(context, this); 104 } else { 105 int shortcutsCount = Math.max(0, 106 (int) mWidgets.stream().filter(WidgetItem::isShortcut).count()); 107 return buildWidgetsCountString(context, mVisibleWidgetsCount, shortcutsCount); 108 } 109 } 110 111 @Override equals(Object obj)112 public boolean equals(Object obj) { 113 if (!(obj instanceof WidgetsListHeaderEntry)) return false; 114 WidgetsListHeaderEntry otherEntry = (WidgetsListHeaderEntry) obj; 115 return mWidgets.equals(otherEntry.mWidgets) && mPkgItem.equals(otherEntry.mPkgItem) 116 && mTitleSectionName.equals(otherEntry.mTitleSectionName) 117 && mIsWidgetListShown == otherEntry.mIsWidgetListShown 118 && mVisibleWidgetsCount == otherEntry.mVisibleWidgetsCount 119 && mIsSearchEntry == otherEntry.mIsSearchEntry; 120 } 121 122 /** Returns a copy of this {@link WidgetsListHeaderEntry} with the widget list shown. */ withWidgetListShown()123 public WidgetsListHeaderEntry withWidgetListShown() { 124 if (mIsWidgetListShown) return this; 125 return new WidgetsListHeaderEntry( 126 mPkgItem, 127 mTitleSectionName, 128 mWidgets, 129 mVisibleWidgetsCount, 130 mIsSearchEntry, 131 /* isWidgetListShown= */ true); 132 } 133 create(PackageItemInfo pkgItem, String titleSectionName, List<WidgetItem> items)134 public static WidgetsListHeaderEntry create(PackageItemInfo pkgItem, String titleSectionName, 135 List<WidgetItem> items) { 136 return new WidgetsListHeaderEntry( 137 pkgItem, 138 titleSectionName, 139 items, 140 /* isSearchEntry= */ false, 141 /* isWidgetListShown= */ false); 142 } 143 144 /** 145 * Creates a widget list holder for an header ("app" / "suggestions") which has widgets or/and 146 * shortcuts. 147 * 148 * @param pkgItem package item info for the header section 149 * @param titleSectionName title string for the header 150 * @param items all items for the given header 151 * @param visibleWidgetsCount widgets count when only selected widgets are shown due to 152 * limited space. 153 */ create(PackageItemInfo pkgItem, String titleSectionName, List<WidgetItem> items, int visibleWidgetsCount)154 public static WidgetsListHeaderEntry create(PackageItemInfo pkgItem, String titleSectionName, 155 List<WidgetItem> items, int visibleWidgetsCount) { 156 return new WidgetsListHeaderEntry( 157 pkgItem, 158 titleSectionName, 159 items, 160 visibleWidgetsCount, 161 /* isSearchEntry= */ false, 162 /* isWidgetListShown= */ false); 163 } 164 createForSearch(PackageItemInfo pkgItem, String titleSectionName, List<WidgetItem> items)165 public static WidgetsListHeaderEntry createForSearch(PackageItemInfo pkgItem, 166 String titleSectionName, List<WidgetItem> items) { 167 return new WidgetsListHeaderEntry( 168 pkgItem, 169 titleSectionName, 170 items, 171 /* isSearchEntry */ true, 172 /* isWidgetListShown= */ false); 173 } 174 } 175