summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/Launcher.java12
-rw-r--r--src/com/android/launcher3/Workspace.java37
-rw-r--r--src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java2
-rw-r--r--src/com/android/launcher3/dot/FolderDotInfo.java13
-rw-r--r--src/com/android/launcher3/folder/Folder.java162
-rw-r--r--src/com/android/launcher3/folder/FolderIcon.java107
-rw-r--r--src/com/android/launcher3/model/ModelWriter.java2
-rw-r--r--src/com/android/launcher3/model/data/FolderInfo.java106
-rw-r--r--src/com/android/launcher3/model/data/ItemInfo.java9
-rw-r--r--src/com/android/launcher3/popup/PopupDataProvider.java7
10 files changed, 147 insertions, 310 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 289f175aa9..5c9392d69d 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1472,8 +1472,7 @@ public class Launcher extends StatefulActivity<LauncherState>
// Adding a shortcut to a Folder.
FolderIcon folderIcon = findFolderIcon(container);
if (folderIcon != null) {
- FolderInfo folderInfo = (FolderInfo) folderIcon.getTag();
- folderInfo.add(info, args.rank, false);
+ folderIcon.getFolder().addFolderContent(info, args.rank, false);
} else {
Log.e(TAG, "Could not find folder with id " + container + " to add shortcut.");
}
@@ -1792,7 +1791,6 @@ public class Launcher extends StatefulActivity<LauncherState>
SettingsCache.INSTANCE.get(this).unregister(TOUCHPAD_NATURAL_SCROLLING,
mNaturalScrollingChangedListener);
ScreenOnTracker.INSTANCE.get(this).removeListener(mScreenOnListener);
- mWorkspace.removeFolderListeners();
PluginManagerWrapper.INSTANCE.get(this).removePluginListener(this);
mModel.removeCallbacks(this);
@@ -2053,9 +2051,10 @@ public class Launcher extends StatefulActivity<LauncherState>
@Nullable final String reason) {
if (itemInfo instanceof WorkspaceItemInfo) {
View collectionIcon = mWorkspace.getViewByItemId(itemInfo.container);
- if (collectionIcon instanceof FolderIcon) {
+ if (collectionIcon instanceof FolderIcon folderIcon) {
// Remove the shortcut from the folder before removing it from launcher
- ((FolderInfo) collectionIcon.getTag()).remove((WorkspaceItemInfo) itemInfo, true);
+ Folder folder = folderIcon.getFolder();
+ folder.removeFolderContent(true, itemInfo);
} else if (collectionIcon instanceof AppPairIcon appPairIcon) {
removeItem(appPairIcon, appPairIcon.getInfo(), deleteFromDb,
"removing app pair because one of its member apps was removed");
@@ -2066,9 +2065,6 @@ public class Launcher extends StatefulActivity<LauncherState>
getModelWriter().deleteItemFromDatabase(itemInfo, reason);
}
} else if (itemInfo instanceof CollectionInfo ci) {
- if (v instanceof FolderIcon) {
- ((FolderIcon) v).removeListeners();
- }
mWorkspace.removeWorkspaceItem(v);
if (deleteFromDb) {
getModelWriter().deleteCollectionAndContentsFromDatabase(ci);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 6ed183ab23..59f84ab891 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -137,7 +137,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
/**
* The workspace is a wide area with a wallpaper and a finite number of pages.
@@ -659,7 +658,6 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
}
// Remove the pages and clear the screen models
- removeFolderListeners();
removeAllViews();
mScreenOrder.clear();
mWorkspaceScreens.clear();
@@ -1914,7 +1912,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
boolean aboveShortcut = Folder.willAccept(dropOverView.getTag())
&& ((ItemInfo) dropOverView.getTag()).container != CONTAINER_HOTSEAT_PREDICTION;
- boolean willBecomeShortcut = Folder.willAcceptItemType(info.itemType);
+ boolean willBecomeShortcut = FolderInfo.willAcceptItemType(info.itemType);
return (aboveShortcut && willBecomeShortcut);
}
@@ -1994,8 +1992,8 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
fi.performCreateAnimation(destInfo, v, sourceInfo, d, folderLocation, scale);
} else {
fi.prepareCreateAnimation(v);
- fi.addItem(destInfo);
- fi.addItem(sourceInfo);
+ fi.getFolder().addFolderContent(destInfo);
+ fi.getFolder().addFolderContent(sourceInfo);
}
return true;
}
@@ -3209,21 +3207,6 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
});
}
- /**
- * Removes all folder listeners
- */
- public void removeFolderListeners() {
- mapOverItems(new ItemOperator() {
- @Override
- public boolean evaluate(ItemInfo info, View view) {
- if (view instanceof FolderIcon) {
- ((FolderIcon) view).removeListeners();
- }
- return false;
- }
- });
- }
-
public boolean isDropEnabled() {
return true;
}
@@ -3349,15 +3332,15 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
if (child instanceof DropTarget) {
mDragController.removeDropTarget((DropTarget) child);
}
- } else if (child instanceof FolderIcon) {
+ } else if (child instanceof FolderIcon folderIcon) {
FolderInfo folderInfo = (FolderInfo) info;
- List<ItemInfo> matches = folderInfo.getContents().stream()
+ ItemInfo[] matches = folderInfo.getContents().stream()
.filter(matcher)
- .collect(Collectors.toList());
- if (!matches.isEmpty()) {
- folderInfo.removeAll(matches, false);
- if (((FolderIcon) child).getFolder().isOpen()) {
- ((FolderIcon) child).getFolder().close(false /* animate */);
+ .toArray(ItemInfo[]::new);
+ if (matches.length > 0) {
+ folderIcon.getFolder().removeFolderContent(false, matches);
+ if (folderIcon.getFolder().isOpen()) {
+ folderIcon.getFolder().close(false /* animate */);
}
}
} else if (info instanceof AppPairInfo api) {
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index cd91f8e00b..df34ccf090 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -519,7 +519,7 @@ public class LauncherAccessibilityDelegate extends BaseAccessibilityDelegate<Lau
Folder folder = Folder.getOpen(mContext);
folder.close(true);
WorkspaceItemInfo info = (WorkspaceItemInfo) item;
- folder.getInfo().remove(info, false);
+ folder.removeFolderContent(false, info);
final int[] coordinates = new int[2];
final int screenId = findSpaceOnWorkspace(item, coordinates);
diff --git a/src/com/android/launcher3/dot/FolderDotInfo.java b/src/com/android/launcher3/dot/FolderDotInfo.java
index 54800a07a8..cb91db7654 100644
--- a/src/com/android/launcher3/dot/FolderDotInfo.java
+++ b/src/com/android/launcher3/dot/FolderDotInfo.java
@@ -30,6 +30,10 @@ public class FolderDotInfo extends DotInfo {
private int mNumNotifications;
+ public void reset() {
+ mNumNotifications = 0;
+ }
+
public void addDotInfo(DotInfo dotToAdd) {
if (dotToAdd == null) {
return;
@@ -39,15 +43,6 @@ public class FolderDotInfo extends DotInfo {
mNumNotifications, MIN_COUNT, DotInfo.MAX_COUNT);
}
- public void subtractDotInfo(DotInfo dotToSubtract) {
- if (dotToSubtract == null) {
- return;
- }
- mNumNotifications -= dotToSubtract.getNotificationKeys().size();
- mNumNotifications = Utilities.boundToRange(
- mNumNotifications, MIN_COUNT, DotInfo.MAX_COUNT);
- }
-
@Override
public int getNotificationCount() {
return mNumNotifications;
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 0ae95196fd..967af053fb 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -19,9 +19,6 @@ package com.android.launcher3.folder;
import static android.text.TextUtils.isEmpty;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.LauncherState.EDIT_MODE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
@@ -29,6 +26,7 @@ import static com.android.launcher3.config.FeatureFlags.ALWAYS_USE_HARDWARE_OPTI
import static com.android.launcher3.folder.FolderGridOrganizer.createFolderGridOrganizer;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_LABEL_UPDATED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED;
+import static com.android.launcher3.model.data.FolderInfo.willAcceptItemType;
import static com.android.launcher3.testing.shared.TestProtocol.FOLDER_OPENED_MESSAGE;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
@@ -95,7 +93,6 @@ import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.data.FolderInfo;
-import com.android.launcher3.model.data.FolderInfo.FolderListener;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -111,6 +108,7 @@ import com.android.launcher3.widget.PendingAddShortcutInfo;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
@@ -122,7 +120,7 @@ import java.util.stream.Stream;
* Represents a set of icons chosen by the user or generated by the system.
*/
public class Folder extends AbstractFloatingView implements ClipPathView, DragSource,
- View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
+ View.OnLongClickListener, DropTarget, TextView.OnEditorActionListener,
View.OnFocusChangeListener, DragListener, ExtendedEditText.OnBackKeyListener,
LauncherBindableItemsContainer {
private static final String TAG = "Launcher.Folder";
@@ -179,15 +177,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
return o instanceof ItemInfo info && willAcceptItemType(info.itemType);
}
- /**
- * Checks if {@code itemType} is a type that can be placed in folders.
- */
- public static boolean willAcceptItemType(int itemType) {
- return itemType == ITEM_TYPE_APPLICATION
- || itemType == ITEM_TYPE_DEEP_SHORTCUT
- || itemType == ITEM_TYPE_APP_PAIR;
- }
-
private Alarm mReorderAlarm = new Alarm(Looper.getMainLooper());
private Alarm mOnExitAlarm = new Alarm(Looper.getMainLooper());
private Alarm mOnScrollHintAlarm = new Alarm(Looper.getMainLooper());
@@ -243,7 +232,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
private boolean mIsExternalDrag;
private boolean mIsDragInProgress = false;
private boolean mDeleteFolderOnDropCompleted = false;
+
private boolean mSuppressFolderDeletion = false;
+ private boolean mSuppressContentUpdate = false;
+
private boolean mItemAddedBackToSelfViaIcon = false;
private boolean mIsEditingName = false;
@@ -385,9 +377,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
// We do not want to get events for the item being removed, as they will get handled
// when the drop completes
- try (SuppressInfoChanges s = new SuppressInfoChanges()) {
- mInfo.remove(dragObject.dragInfo, true);
- }
+ executeWithContentUpdateSuppressed(() -> removeFolderContent(true, dragObject.dragInfo));
+
mIsDragInProgress = true;
mItemAddedBackToSelfViaIcon = false;
}
@@ -532,8 +523,17 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
lp.customPosition = true;
setLayoutParams(lp);
}
+ reapplyItemInfo();
+ // In case any children didn't come across during loading, clean up the folder accordingly
+ mFolderIcon.post(() -> {
+ if (getItemCount() <= 1) {
+ replaceFolderWithFinalItem();
+ }
+ });
+ }
+
+ public void reapplyItemInfo() {
mItemsInvalidated = true;
- mInfo.addListener(this);
if (!isEmpty(mInfo.title)) {
mFolderName.setText(mInfo.title);
@@ -542,15 +542,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
mFolderName.setText("");
mFolderName.setHint(R.string.folder_hint_text);
}
- // In case any children didn't come across during loading, clean up the folder accordingly
- mFolderIcon.post(() -> {
- if (getItemCount() <= 1) {
- replaceFolderWithFinalItem();
- }
- });
}
-
/**
* Show suggested folder title in FolderEditText if the first suggestion is non-empty, push
* rest of the suggestions to InputMethodManager.
@@ -680,7 +673,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
if (!shouldAnimateOpen(items)) {
return;
}
-
Folder openFolder = getOpen(mActivityContext);
closeOpenFolder(openFolder);
@@ -954,9 +946,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
@Override
public boolean acceptDrop(DragObject d) {
- final ItemInfo item = d.dragInfo;
- final int itemType = item.itemType;
- return Folder.willAcceptItemType(itemType);
+ return willAcceptItemType(d.dragInfo.itemType);
}
public void onDragEnter(DragObject d) {
@@ -1121,9 +1111,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
mContent.arrangeChildren(views);
mItemsInvalidated = true;
- try (SuppressInfoChanges s = new SuppressInfoChanges()) {
- mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */);
- }
+ executeWithContentUpdateSuppressed(
+ () -> mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */));
}
}
@@ -1417,9 +1406,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
rearrangeChildren();
// Temporarily suppress the listener, as we did all the work already here.
- try (SuppressInfoChanges s = new SuppressInfoChanges()) {
- mInfo.add(si, mEmptyCellRank, false);
- }
+ executeWithContentUpdateSuppressed(() -> addFolderContent(si, mEmptyCellRank, false));
// We only need to update the locations if it doesn't get handled in
// #onDropCompleted.
@@ -1465,37 +1452,66 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
}
}
- @Override
- public void onAdd(ItemInfo item, int rank) {
- FolderGridOrganizer verifier = createFolderGridOrganizer(
- mActivityContext.getDeviceProfile()).setFolderInfo(mInfo);
- verifier.updateRankAndPos(item, rank);
- mLauncherDelegate.getModelWriter().addOrMoveItemInDatabase(item, mInfo.id, 0, item.cellX,
- item.cellY);
- updateItemLocationsInDatabaseBatch(false);
+ /** Add an app or shortcut */
+ public void addFolderContent(ItemInfo item) {
+ addFolderContent(item, mInfo.getContents().size(), true);
+ }
- if (mContent.areViewsBound()) {
- mContent.createAndAddViewForRank(item, rank);
+ /** Add an app or shortcut for a specified rank */
+ public void addFolderContent(ItemInfo item, int rank, boolean animate) {
+ if (!willAcceptItemType(item.itemType)) {
+ throw new RuntimeException("tried to add an illegal type into a folder");
}
- mItemsInvalidated = true;
+
+ rank = Utilities.boundToRange(rank, 0, mInfo.getContents().size());
+ mInfo.getContents().add(rank, item);
+
+ if (!mSuppressContentUpdate) {
+ FolderGridOrganizer verifier = createFolderGridOrganizer(
+ mActivityContext.getDeviceProfile()).setFolderInfo(mInfo);
+ verifier.updateRankAndPos(item, rank);
+ mLauncherDelegate.getModelWriter().addOrMoveItemInDatabase(item, mInfo.id, 0,
+ item.cellX,
+ item.cellY);
+ updateItemLocationsInDatabaseBatch(false);
+
+ if (mContent.areViewsBound()) {
+ mContent.createAndAddViewForRank(item, rank);
+ }
+ mItemsInvalidated = true;
+ updateTextViewFocus();
+ }
+
+ mLauncherDelegate.getModelWriter().notifyItemModified(mInfo);
+ mFolderIcon.onItemsChanged(animate);
}
- @Override
- public void onRemove(List<ItemInfo> items) {
- mItemsInvalidated = true;
- items.stream().map(this::getViewForInfo).forEach(mContent::removeItem);
- if (mState == STATE_ANIMATING) {
- mRearrangeOnClose = true;
- } else {
- rearrangeChildren();
+ /** Remove all matching app or shortcut. Does not change the DB. */
+ public void removeFolderContent(boolean animate, ItemInfo... items) {
+ List<ItemInfo> itemArray = Arrays.asList(items);
+ if (mInfo.getContents().removeAll(itemArray)) {
+ mLauncherDelegate.getModelWriter().notifyItemModified(mInfo);
}
- if (getItemCount() <= 1) {
- if (mIsOpen) {
- close(true);
+
+ if (!mSuppressContentUpdate) {
+ mItemsInvalidated = true;
+ itemArray.forEach(item -> mContent.removeItem(getViewForInfo(item)));
+ if (mState == STATE_ANIMATING) {
+ mRearrangeOnClose = true;
} else {
- replaceFolderWithFinalItem();
+ rearrangeChildren();
+ }
+ if (getItemCount() <= 1) {
+ if (mIsOpen) {
+ close(true);
+ } else {
+ replaceFolderWithFinalItem();
+ }
}
+ updateTextViewFocus();
}
+
+ mFolderIcon.onItemsChanged(animate);
}
@VisibleForTesting
@@ -1503,16 +1519,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
return mContent.iterateOverItems((info, view) -> info == item);
}
- @Override
- public void onItemsChanged(boolean animate) {
- updateTextViewFocus();
- }
-
- @Override
- public void onTitleChanged(CharSequence title) {
- mFolderName.setText(title);
- }
-
/**
* Utility methods to iterate over items of the view
*/
@@ -1666,18 +1672,14 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
}
};
- /**
- * Temporary resource held while we don't want to handle info changes
- */
- private class SuppressInfoChanges implements AutoCloseable {
-
- SuppressInfoChanges() {
- mInfo.removeListener(Folder.this);
- }
-
- @Override
- public void close() {
- mInfo.addListener(Folder.this);
+ /** Executes the task while suppressing the content update for the folder */
+ private void executeWithContentUpdateSuppressed(Runnable task) {
+ if (mSuppressContentUpdate) {
+ task.run();
+ } else {
+ mSuppressContentUpdate = true;
+ task.run();
+ mSuppressContentUpdate = false;
updateTextViewFocus();
}
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 0ed87871cc..1cd9bcc965 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -23,6 +23,7 @@ import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMA
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_AUTO_LABELED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_AUTO_LABELING_SKIPPED_EMPTY_PRIMARY;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_AUTO_LABELING_SKIPPED_EMPTY_SUGGESTIONS;
+import static com.android.launcher3.model.data.FolderInfo.willAcceptItemType;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -73,7 +74,6 @@ import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.AppPairInfo;
import com.android.launcher3.model.data.FolderInfo;
-import com.android.launcher3.model.data.FolderInfo.FolderListener;
import com.android.launcher3.model.data.FolderInfo.LabelState;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemFactory;
@@ -92,7 +92,7 @@ import java.util.function.Predicate;
/**
* An icon that can appear on in the workspace representing an {@link Folder}.
*/
-public class FolderIcon extends FrameLayout implements FolderListener, FloatingIconViewCompanion,
+public class FolderIcon extends FrameLayout implements FloatingIconViewCompanion,
DraggableView, Reorderable {
private final MultiTranslateDelegate mTranslateDelegate = new MultiTranslateDelegate(this);
@@ -127,7 +127,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
private boolean mForceHideDot;
@ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
- private FolderDotInfo mDotInfo = new FolderDotInfo();
+ private final FolderDotInfo mDotInfo = new FolderDotInfo();
private DotRenderer mDotRenderer;
@ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
private DotRenderer.DrawParams mDotParams;
@@ -178,7 +178,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
folder.bind(folderInfo);
icon.setFolder(folder);
- folderInfo.addListener(icon);
return icon;
}
@@ -217,13 +216,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
icon.mDotRenderer = grid.mDotRendererWorkSpace;
icon.setContentDescription(icon.getAccessiblityTitle(folderInfo.title));
-
- // Keep the notification dot up to date with the sum of all the content's dots.
- FolderDotInfo folderDotInfo = new FolderDotInfo();
- for (ItemInfo si : folderInfo.getContents()) {
- folderDotInfo.addDotInfo(activity.getDotInfoForItem(si));
- }
- icon.setDotInfo(folderDotInfo);
+ icon.updateDotInfo();
icon.setAccessibilityDelegate(activity.getAccessibilityDelegate());
@@ -264,22 +257,13 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
}
private boolean willAcceptItem(ItemInfo item) {
- final int itemType = item.itemType;
- return (Folder.willAcceptItemType(itemType) && item != mInfo && !mFolder.isOpen());
+ return (willAcceptItemType(item.itemType) && item != mInfo && !mFolder.isOpen());
}
public boolean acceptDrop(ItemInfo dragInfo) {
return !mFolder.isDestroyed() && willAcceptItem(dragInfo);
}
- public void addItem(ItemInfo item) {
- mInfo.add(item, true);
- }
-
- public void removeItem(ItemInfo item, boolean animate) {
- mInfo.remove(item, animate);
- }
-
public void onDragEnter(ItemInfo dragInfo) {
if (mFolder.isDestroyed() || !willAcceptItem(dragInfo)) return;
CellLayoutLayoutParams lp = (CellLayoutLayoutParams) getLayoutParams();
@@ -308,9 +292,8 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
public void performCreateAnimation(final ItemInfo destInfo, final View destView,
final ItemInfo srcInfo, final DragObject d, Rect dstRect,
float scaleRelativeToDragLayer) {
- final DragView srcView = d.dragView;
prepareCreateAnimation(destView);
- addItem(destInfo);
+ getFolder().addFolderContent(destInfo);
// This will animate the first item from it's position as an icon into its
// position as the first item in the preview
mPreviewItemManager.createFirstItemAnimation(false /* reverse */, null)
@@ -364,7 +347,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
boolean itemAdded = false;
if (itemReturnedOnFailedDrop || index >= MAX_NUM_ITEMS_IN_PREVIEW) {
List<ItemInfo> oldPreviewItems = new ArrayList<>(mCurrentPreviewItems);
- mInfo.add(item, index, false);
+ getFolder().addFolderContent(item, index, false);
mCurrentPreviewItems.clear();
mCurrentPreviewItems.addAll(getPreviewItemsOnPage(0));
@@ -380,12 +363,12 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
mPreviewItemManager.onDrop(oldPreviewItems, mCurrentPreviewItems, item);
itemAdded = true;
} else {
- removeItem(item, false);
+ getFolder().removeFolderContent(false, item);
}
}
if (!itemAdded) {
- mInfo.add(item, index, true);
+ getFolder().addFolderContent(item, index, true);
}
int[] center = new int[2];
@@ -431,7 +414,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
}, DROP_IN_ANIMATION_DURATION);
});
} else {
- addItem(item);
+ getFolder().addFolderContent(item);
}
}
@@ -500,9 +483,23 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
);
}
- public void setDotInfo(FolderDotInfo dotInfo) {
- updateDotScale(mDotInfo.hasDot(), dotInfo.hasDot());
- mDotInfo = dotInfo;
+ /** Keep the notification dot up to date with the sum of all the content's dots. */
+ public void updateDotInfo() {
+ boolean hadDot = mDotInfo.hasDot();
+ mDotInfo.reset();
+ for (ItemInfo si : mInfo.getContents()) {
+ mDotInfo.addDotInfo(mActivity.getDotInfoForItem(si));
+ }
+ boolean isDotted = mDotInfo.hasDot();
+ float newDotScale = isDotted ? 1f : 0f;
+ // Animate when a dot is first added or when it is removed.
+ if ((hadDot ^ isDotted) && isShown()) {
+ animateDotScale(newDotScale);
+ } else {
+ cancelDotScaleAnim();
+ mDotScale = newDotScale;
+ invalidate();
+ }
}
public ClippedFolderIconLayoutRule getLayoutRule() {
@@ -523,22 +520,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
}
}
- /**
- * Sets mDotScale to 1 or 0, animating if wasDotted or isDotted is false
- * (the dot is being added or removed).
- */
- private void updateDotScale(boolean wasDotted, boolean isDotted) {
- float newDotScale = isDotted ? 1f : 0f;
- // Animate when a dot is first added or when it is removed.
- if ((wasDotted ^ isDotted) && isShown()) {
- animateDotScale(newDotScale);
- } else {
- cancelDotScaleAnim();
- mDotScale = newDotScale;
- invalidate();
- }
- }
-
private void cancelDotScaleAnim() {
if (mDotScaleAnim != null) {
mDotScaleAnim.cancel();
@@ -682,13 +663,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
return mPreviewItemManager.verifyDrawable(who) || super.verifyDrawable(who);
}
- @Override
- public void onItemsChanged(boolean animate) {
- updatePreviewItems(animate);
- invalidate();
- requestLayout();
- }
-
private void updatePreviewItems(boolean animate) {
mPreviewItemManager.updatePreviewItems(animate);
mCurrentPreviewItems.clear();
@@ -702,31 +676,15 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
mPreviewItemManager.updatePreviewItems(itemCheck);
}
- @Override
- public void onAdd(ItemInfo item, int rank) {
- updatePreviewItems(false);
- boolean wasDotted = mDotInfo.hasDot();
- mDotInfo.addDotInfo(mActivity.getDotInfoForItem(item));
- boolean isDotted = mDotInfo.hasDot();
- updateDotScale(wasDotted, isDotted);
- setContentDescription(getAccessiblityTitle(mInfo.title));
- invalidate();
- requestLayout();
- }
-
- @Override
- public void onRemove(List<ItemInfo> items) {
+ public void onItemsChanged(boolean animate) {
updatePreviewItems(false);
- boolean wasDotted = mDotInfo.hasDot();
- items.stream().map(mActivity::getDotInfoForItem).forEach(mDotInfo::subtractDotInfo);
- boolean isDotted = mDotInfo.hasDot();
- updateDotScale(wasDotted, isDotted);
+ updateDotInfo();
setContentDescription(getAccessiblityTitle(mInfo.title));
+ updatePreviewItems(animate);
invalidate();
requestLayout();
}
- @Override
public void onTitleChanged(CharSequence title) {
mFolderName.setText(title);
setContentDescription(getAccessiblityTitle(title));
@@ -762,11 +720,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
mLongPressHelper.cancelLongPress();
}
- public void removeListeners() {
- mInfo.removeListener(this);
- mInfo.removeListener(mFolder);
- }
-
private boolean isInHotseat() {
return mInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT;
}
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index 0332775224..dc103a6a3d 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -229,7 +229,7 @@ public class ModelWriter {
}).executeOnModelThread();
}
- private void notifyItemModified(ItemInfo item) {
+ public void notifyItemModified(ItemInfo item) {
notifyOtherCallbacks(c -> c.bindItemsModified(Collections.singletonList(item)));
}
diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java
index 9656ac10b2..4c792a7672 100644
--- a/src/com/android/launcher3/model/data/FolderInfo.java
+++ b/src/com/android/launcher3/model/data/FolderInfo.java
@@ -20,6 +20,9 @@ import static android.text.TextUtils.isEmpty;
import static androidx.core.util.Preconditions.checkNotNull;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.logger.LauncherAtom.Attribute.EMPTY_LABEL;
import static com.android.launcher3.logger.LauncherAtom.Attribute.MANUAL_LABEL;
import static com.android.launcher3.logger.LauncherAtom.Attribute.SUGGESTED_LABEL;
@@ -30,8 +33,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderNameInfos;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.Attribute;
@@ -42,8 +43,6 @@ import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.util.ContentWriter;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
import java.util.OptionalInt;
import java.util.stream.IntStream;
@@ -52,18 +51,6 @@ import java.util.stream.IntStream;
*/
public class FolderInfo extends CollectionInfo {
- public static final int NO_FLAGS = 0x00000000;
-
- /**
- * The folder is locked in sorted mode
- */
- public static final int FLAG_ITEMS_SORTED = 0x00000001;
-
- /**
- * It is a work folder
- */
- public static final int FLAG_WORK_FOLDER = 0x00000002;
-
/**
* The multi-page animation has run for this folder
*/
@@ -95,8 +82,6 @@ public class FolderInfo extends CollectionInfo {
}
}
- public static final String EXTRA_FOLDER_SUGGESTIONS = "suggest";
-
public int options;
public FolderNameInfos suggestedFolderNames;
@@ -106,61 +91,16 @@ public class FolderInfo extends CollectionInfo {
*/
private final ArrayList<ItemInfo> contents = new ArrayList<>();
- private ArrayList<FolderListener> mListeners = new ArrayList<>();
-
public FolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
}
- /** Adds a app or shortcut to the contents ArrayList without animation. */
@Override
public void add(@NonNull ItemInfo item) {
- add(item, false /* animate */);
- }
-
- /**
- * Add an app or shortcut
- *
- * @param item
- */
- public void add(ItemInfo item, boolean animate) {
- add(item, getContents().size(), animate);
- }
-
- /**
- * Add an app or shortcut for a specified rank.
- */
- public void add(ItemInfo item, int rank, boolean animate) {
- if (!Folder.willAccept(item)) {
+ if (!willAcceptItemType(item.itemType)) {
throw new RuntimeException("tried to add an illegal type into a folder");
}
-
- rank = Utilities.boundToRange(rank, 0, getContents().size());
- getContents().add(rank, item);
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onAdd(item, rank);
- }
- itemsChanged(animate);
- }
-
- /**
- * Remove an app or shortcut. Does not change the DB.
- *
- * @param item
- */
- public void remove(ItemInfo item, boolean animate) {
- removeAll(Collections.singletonList(item), animate);
- }
-
- /**
- * Remove all matching app or shortcut. Does not change the DB.
- */
- public void removeAll(List<ItemInfo> items, boolean animate) {
- contents.removeAll(items);
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onRemove(items);
- }
- itemsChanged(animate);
+ getContents().add(item);
}
/**
@@ -197,28 +137,6 @@ public class FolderInfo extends CollectionInfo {
writer.put(LauncherSettings.Favorites.OPTIONS, options);
}
- public void addListener(FolderListener listener) {
- mListeners.add(listener);
- }
-
- public void removeListener(FolderListener listener) {
- mListeners.remove(listener);
- }
-
- public void itemsChanged(boolean animate) {
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onItemsChanged(animate);
- }
- }
-
- public interface FolderListener {
- void onAdd(ItemInfo item, int rank);
- void onRemove(List<ItemInfo> item);
- void onItemsChanged(boolean animate);
- void onTitleChanged(CharSequence title);
-
- }
-
public boolean hasOption(int optionFlag) {
return (options & optionFlag) != 0;
}
@@ -261,7 +179,6 @@ public class FolderInfo extends CollectionInfo {
.build();
}
- @Override
public void setTitle(@Nullable CharSequence title, ModelWriter modelWriter) {
// Updating label from null to empty is considered as false touch.
// Retaining null title(ie., UNLABELED state) allows auto-labeling when new items added.
@@ -289,10 +206,6 @@ public class FolderInfo extends CollectionInfo {
if (modelWriter != null) {
modelWriter.updateItemInDatabase(this);
}
-
- for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onTitleChanged(title);
- }
}
/**
@@ -401,4 +314,13 @@ public class FolderInfo extends CollectionInfo {
}
return LauncherAtom.ToState.TO_STATE_UNSPECIFIED;
}
+
+ /**
+ * Checks if {@code itemType} is a type that can be placed in folders.
+ */
+ public static boolean willAcceptItemType(int itemType) {
+ return itemType == ITEM_TYPE_APPLICATION
+ || itemType == ITEM_TYPE_DEEP_SHORTCUT
+ || itemType == ITEM_TYPE_APP_PAIR;
+ }
}
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 588e75959e..ad7696cd15 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -61,7 +61,6 @@ import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer;
import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer;
import com.android.launcher3.logger.LauncherAtom.WallpapersContainer;
import com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers;
-import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ContentWriter;
@@ -536,14 +535,6 @@ public class ItemInfo {
}
/**
- * Sets the title of the item and writes to DB model if needed.
- */
- public void setTitle(@Nullable final CharSequence title,
- @Nullable final ModelWriter modelWriter) {
- this.title = title;
- }
-
- /**
* Returns a string ID that is stable for a user session, but may not be persisted
*/
@Nullable
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index 5c1a7553a5..95110329d3 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -26,7 +26,6 @@ import androidx.annotation.Nullable;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
import com.android.launcher3.dot.DotInfo;
-import com.android.launcher3.dot.FolderDotInfo;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.model.data.FolderInfo;
@@ -76,11 +75,7 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
((BubbleTextView) v).applyDotState(info, true /* animate */);
} else if (v instanceof FolderIcon icon
&& info instanceof FolderInfo fi && fi.anyMatch(matcher)) {
- FolderDotInfo folderDotInfo = new FolderDotInfo();
- for (ItemInfo si : fi.getContents()) {
- folderDotInfo.addDotInfo(getDotInfoForItem(si));
- }
- icon.setDotInfo(folderDotInfo);
+ icon.updateDotInfo();
}
// process all the shortcuts