2021-11-22 16:54:54 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2022 The Android Open Source Project
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
package com.android.launcher3.model;
|
|
|
|
|
|
|
|
|
|
import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
|
|
|
|
|
|
|
|
|
|
import android.util.LongSparseArray;
|
|
|
|
|
|
|
|
|
|
import com.android.launcher3.InvariantDeviceProfile;
|
|
|
|
|
import com.android.launcher3.LauncherAppState;
|
|
|
|
|
import com.android.launcher3.LauncherSettings;
|
|
|
|
|
import com.android.launcher3.config.FeatureFlags;
|
|
|
|
|
import com.android.launcher3.model.data.ItemInfo;
|
|
|
|
|
import com.android.launcher3.util.GridOccupancy;
|
|
|
|
|
import com.android.launcher3.util.IntArray;
|
|
|
|
|
import com.android.launcher3.util.IntSet;
|
|
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Utility class to help find space for new workspace items
|
|
|
|
|
*/
|
|
|
|
|
public class WorkspaceItemSpaceFinder {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Find a position on the screen for the given size or adds a new screen.
|
|
|
|
|
*
|
|
|
|
|
* @return screenId and the coordinates for the item in an int array of size 3.
|
|
|
|
|
*/
|
|
|
|
|
public int[] findSpaceForItem(LauncherAppState app, BgDataModel dataModel,
|
|
|
|
|
IntArray workspaceScreens, IntArray addedWorkspaceScreensFinal, int spanX, int spanY) {
|
|
|
|
|
LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();
|
|
|
|
|
|
|
|
|
|
// Use sBgItemsIdMap as all the items are already loaded.
|
|
|
|
|
synchronized (dataModel) {
|
|
|
|
|
for (ItemInfo info : dataModel.itemsIdMap) {
|
|
|
|
|
if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
|
|
|
|
ArrayList<ItemInfo> items = screenItems.get(info.screenId);
|
|
|
|
|
if (items == null) {
|
|
|
|
|
items = new ArrayList<>();
|
|
|
|
|
screenItems.put(info.screenId, items);
|
|
|
|
|
}
|
|
|
|
|
items.add(info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Find appropriate space for the item.
|
|
|
|
|
int screenId = 0;
|
|
|
|
|
int[] coordinates = new int[2];
|
|
|
|
|
boolean found = false;
|
|
|
|
|
|
|
|
|
|
int screenCount = workspaceScreens.size();
|
|
|
|
|
// First check the preferred screen.
|
|
|
|
|
IntSet screensToExclude = new IntSet();
|
|
|
|
|
if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
|
|
|
|
|
screensToExclude.add(FIRST_SCREEN_ID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int screen = 0; screen < screenCount; screen++) {
|
|
|
|
|
screenId = workspaceScreens.get(screen);
|
|
|
|
|
if (!screensToExclude.contains(screenId) && findNextAvailableIconSpaceInScreen(
|
|
|
|
|
app, screenItems.get(screenId), coordinates, spanX, spanY)) {
|
|
|
|
|
// We found a space for it
|
|
|
|
|
found = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
|
// Still no position found. Add a new screen to the end.
|
2023-05-17 12:44:03 -07:00
|
|
|
screenId = app.getModel().getModelDbController().getNewScreenId();
|
2021-11-22 16:54:54 +00:00
|
|
|
|
|
|
|
|
// Save the screen id for binding in the workspace
|
|
|
|
|
workspaceScreens.add(screenId);
|
|
|
|
|
addedWorkspaceScreensFinal.add(screenId);
|
|
|
|
|
|
|
|
|
|
// If we still can't find an empty space, then God help us all!!!
|
|
|
|
|
if (!findNextAvailableIconSpaceInScreen(
|
|
|
|
|
app, screenItems.get(screenId), coordinates, spanX, spanY)) {
|
|
|
|
|
throw new RuntimeException("Can't find space to add the item");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return new int[]{screenId, coordinates[0], coordinates[1]};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean findNextAvailableIconSpaceInScreen(
|
|
|
|
|
LauncherAppState app, ArrayList<ItemInfo> occupiedPos,
|
|
|
|
|
int[] xy, int spanX, int spanY) {
|
|
|
|
|
InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
|
|
|
|
|
|
|
|
|
|
GridOccupancy occupied = new GridOccupancy(profile.numColumns, profile.numRows);
|
|
|
|
|
if (occupiedPos != null) {
|
|
|
|
|
for (ItemInfo r : occupiedPos) {
|
|
|
|
|
occupied.markCells(r, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return occupied.findVacantCell(xy, spanX, spanY);
|
|
|
|
|
}
|
|
|
|
|
}
|