1 /* 2 * Copyright (C) 2019 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 com.android.launcher3.InvariantDeviceProfile; 19 import com.android.launcher3.LauncherSettings; 20 import com.android.launcher3.config.FeatureFlags; 21 import com.android.launcher3.model.data.ItemInfo; 22 import com.android.launcher3.util.IntArray; 23 import com.android.launcher3.util.IntSet; 24 25 import java.util.ArrayList; 26 import java.util.Collections; 27 import java.util.Iterator; 28 import java.util.List; 29 import java.util.stream.IntStream; 30 31 /** 32 * Utils class for {@link com.android.launcher3.LauncherModel}. 33 */ 34 public class ModelUtils { 35 36 /** 37 * Filters the set of items who are directly or indirectly (via another container) on the 38 * specified screen. 39 */ filterCurrentWorkspaceItems(int currentScreenId, ArrayList<T> allWorkspaceItems, ArrayList<T> currentScreenItems, ArrayList<T> otherScreenItems)40 public static <T extends ItemInfo> void filterCurrentWorkspaceItems(int currentScreenId, 41 ArrayList<T> allWorkspaceItems, 42 ArrayList<T> currentScreenItems, 43 ArrayList<T> otherScreenItems) { 44 // Purge any null ItemInfos 45 Iterator<T> iter = allWorkspaceItems.iterator(); 46 while (iter.hasNext()) { 47 ItemInfo i = iter.next(); 48 if (i == null) { 49 iter.remove(); 50 } 51 } 52 // Order the set of items by their containers first, this allows use to walk through the 53 // list sequentially, build up a list of containers that are in the specified screen, 54 // as well as all items in those containers. 55 IntSet itemsOnScreen = new IntSet(); 56 Collections.sort(allWorkspaceItems, 57 (lhs, rhs) -> Integer.compare(lhs.container, rhs.container)); 58 for (T info : allWorkspaceItems) { 59 if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { 60 if (info.screenId == currentScreenId) { 61 currentScreenItems.add(info); 62 itemsOnScreen.add(info.id); 63 } else { 64 otherScreenItems.add(info); 65 } 66 } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { 67 currentScreenItems.add(info); 68 itemsOnScreen.add(info.id); 69 } else { 70 if (itemsOnScreen.contains(info.container)) { 71 currentScreenItems.add(info); 72 itemsOnScreen.add(info.id); 73 } else { 74 otherScreenItems.add(info); 75 } 76 } 77 } 78 } 79 80 /** 81 * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right) 82 */ sortWorkspaceItemsSpatially(InvariantDeviceProfile profile, ArrayList<ItemInfo> workspaceItems)83 public static void sortWorkspaceItemsSpatially(InvariantDeviceProfile profile, 84 ArrayList<ItemInfo> workspaceItems) { 85 final int screenCols = profile.numColumns; 86 final int screenCellCount = profile.numColumns * profile.numRows; 87 Collections.sort(workspaceItems, (lhs, rhs) -> { 88 if (lhs.container == rhs.container) { 89 // Within containers, order by their spatial position in that container 90 switch (lhs.container) { 91 case LauncherSettings.Favorites.CONTAINER_DESKTOP: { 92 int lr = (lhs.screenId * screenCellCount + lhs.cellY * screenCols 93 + lhs.cellX); 94 int rr = (rhs.screenId * screenCellCount + +rhs.cellY * screenCols 95 + rhs.cellX); 96 return Integer.compare(lr, rr); 97 } 98 case LauncherSettings.Favorites.CONTAINER_HOTSEAT: { 99 // We currently use the screen id as the rank 100 return Integer.compare(lhs.screenId, rhs.screenId); 101 } 102 default: 103 if (FeatureFlags.IS_STUDIO_BUILD) { 104 throw new RuntimeException( 105 "Unexpected container type when sorting workspace items."); 106 } 107 return 0; 108 } 109 } else { 110 // Between containers, order by hotseat, desktop 111 return Integer.compare(lhs.container, rhs.container); 112 } 113 }); 114 } 115 116 /** 117 * Iterates though current workspace items and returns available hotseat ranks for prediction. 118 */ getMissingHotseatRanks(List<ItemInfo> items, int len)119 public static IntArray getMissingHotseatRanks(List<ItemInfo> items, int len) { 120 IntSet seen = new IntSet(); 121 items.stream().filter( 122 info -> info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) 123 .forEach(i -> seen.add(i.screenId)); 124 IntArray result = new IntArray(len); 125 IntStream.range(0, len).filter(i -> !seen.contains(i)).forEach(result::add); 126 return result; 127 } 128 } 129