Merge "Wallpaper preview parallax matches the actual wallpaper's." into ub-launcher3-burnaby-polish
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 9c8659c..163ffb6 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -70,40 +70,9 @@
      * @return true if the item was removed.
      */
     public static boolean removeWorkspaceOrFolderItem(Launcher launcher, ItemInfo item, View view) {
-        if (item instanceof ShortcutInfo) {
-            LauncherModel.deleteItemFromDatabase(launcher, item);
-        } else if (item instanceof FolderInfo) {
-            FolderInfo folder = (FolderInfo) item;
-            launcher.removeFolder(folder);
-            LauncherModel.deleteFolderContentsFromDatabase(launcher, folder);
-        } else if (item instanceof LauncherAppWidgetInfo) {
-            final LauncherAppWidgetInfo widget = (LauncherAppWidgetInfo) item;
-
-            // Remove the widget from the workspace
-            launcher.removeAppWidget(widget);
-            LauncherModel.deleteItemFromDatabase(launcher, widget);
-
-            final LauncherAppWidgetHost appWidgetHost = launcher.getAppWidgetHost();
-
-            if (appWidgetHost != null && !widget.isCustomWidget()
-                    && widget.isWidgetIdValid()) {
-                // Deleting an app widget ID is a void call but writes to disk before returning
-                // to the caller...
-                new AsyncTask<Void, Void, Void>() {
-                    public Void doInBackground(Void ... args) {
-                        appWidgetHost.deleteAppWidgetId(widget.appWidgetId);
-                        return null;
-                    }
-                }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-            }
-        } else {
-            return false;
-        }
-
-        if (view != null) {
-            launcher.getWorkspace().removeWorkspaceItem(view);
-            launcher.getWorkspace().stripEmptyScreens();
-        }
+        // Remove the item from launcher and the db
+        launcher.removeItem(view, item, true /* deleteFromDb */);
+        launcher.getWorkspace().stripEmptyScreens();
         return true;
     }
 
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index 57aec32..eca5eec 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -185,7 +185,8 @@
             return consume;
         }
 
-        DeviceProfile profile = ((Launcher) v.getContext()).getDeviceProfile();
+        final Launcher launcher = (Launcher) v.getContext();
+        final DeviceProfile profile = launcher.getDeviceProfile();
 
         if (DEBUG) {
             Log.v(TAG, String.format(
@@ -196,7 +197,6 @@
         // Initialize the variables.
         final ShortcutAndWidgetContainer hotseatParent = (ShortcutAndWidgetContainer) v.getParent();
         final CellLayout hotseatLayout = (CellLayout) hotseatParent.getParent();
-        Hotseat hotseat = (Hotseat) hotseatLayout.getParent();
 
         Workspace workspace = (Workspace) v.getRootView().findViewById(R.id.workspace);
         int pageIndex = workspace.getNextPage();
@@ -240,7 +240,10 @@
         } else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
                 profile.isVerticalBarLayout()) {
             keyCode = KeyEvent.KEYCODE_PAGE_DOWN;
-        }else {
+        } else if (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
+            ItemInfo info = (ItemInfo) v.getTag();
+            launcher.removeItem(v, info, true /* deleteFromDb */);
+        } else {
             // For other KEYCODE_DPAD_LEFT and KEYCODE_DPAD_RIGHT navigation, do not use the
             // matrix extended with hotseat.
             matrix = FocusLogic.createSparseMatrix(hotseatLayout);
@@ -326,7 +329,8 @@
                     !hotseat.hasIcons() /* ignore all apps icon, unless there are no other icons */);
             countX = countX + 1;
         } else if (keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
-            workspace.removeWorkspaceItem(v);
+            ItemInfo info = (ItemInfo) v.getTag();
+            launcher.removeItem(v, info, true /* deleteFromDb */);
             return consume;
         } else {
             matrix = FocusLogic.createSparseMatrix(iconLayout);
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index c1aa356..f59c87e 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -1122,16 +1122,10 @@
                             mInfo.screenId, mInfo.cellX, mInfo.cellY);
                 }
                 if (getItemCount() <= 1) {
-                    // Remove the folder
-                    LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
-                    if (cellLayout != null) {
-                        // b/12446428 -- sometimes the cell layout has already gone away?
-                        cellLayout.removeView(mFolderIcon);
-                    }
+                    mLauncher.removeItem(mFolderIcon, mInfo, true /* deleteFromDb */);
                     if (mFolderIcon instanceof DropTarget) {
                         mDragController.removeDropTarget((DropTarget) mFolderIcon);
                     }
-                    mLauncher.removeFolder(mInfo);
                 }
                 // We add the child after removing the folder to prevent both from existing at
                 // the same time in the CellLayout.  We need to add the new item with addInScreenFromBind()
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index e687ee2..38ba782 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1787,7 +1787,7 @@
         }
     });
 
-    void addWidgetToAutoAdvanceIfNeeded(View hostView, AppWidgetProviderInfo appWidgetInfo) {
+    private void addWidgetToAutoAdvanceIfNeeded(View hostView, AppWidgetProviderInfo appWidgetInfo) {
         if (appWidgetInfo == null || appWidgetInfo.autoAdvanceViewId == -1) return;
         View v = hostView.findViewById(appWidgetInfo.autoAdvanceViewId);
         if (v instanceof Advanceable) {
@@ -1797,18 +1797,13 @@
         }
     }
 
-    void removeWidgetToAutoAdvance(View hostView) {
+    private void removeWidgetToAutoAdvance(View hostView) {
         if (mWidgetsToAdvance.containsKey(hostView)) {
             mWidgetsToAdvance.remove(hostView);
             updateAutoAdvanceState();
         }
     }
 
-    public void removeAppWidget(LauncherAppWidgetInfo launcherInfo) {
-        removeWidgetToAutoAdvance(launcherInfo.hostView);
-        launcherInfo.hostView = null;
-    }
-
     public void showOutOfSpaceMessage(boolean isHotseatLayout) {
         int strId = (isHotseatLayout ? R.string.hotseat_out_of_space : R.string.out_of_space);
         Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show();
@@ -2394,10 +2389,63 @@
         return newFolder;
     }
 
-    void removeFolder(FolderInfo folder) {
+    /**
+     * Unbinds the view for the specified item, and removes the item and all its children items
+     * from the database.  For folders, this incl udes the folder contents.  AppWidgets will also
+     * have their widget ids deleted.
+     */
+    public boolean removeItem(View v, ItemInfo itemInfo, boolean deleteFromDb) {
+        if (itemInfo instanceof ShortcutInfo) {
+            mWorkspace.removeWorkspaceItem(v);
+            if (deleteFromDb) {
+                LauncherModel.deleteItemFromDatabase(this, itemInfo);
+            }
+        } else if (itemInfo instanceof FolderInfo) {
+            final FolderInfo folderInfo = (FolderInfo) itemInfo;
+            unbindFolder(folderInfo);
+            mWorkspace.removeWorkspaceItem(v);
+            if (deleteFromDb) {
+                LauncherModel.deleteFolderAndContentsFromDatabase(this, folderInfo);
+            }
+        } else if (itemInfo instanceof LauncherAppWidgetInfo) {
+            final LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) itemInfo;
+            unbindAppWidget(widgetInfo, deleteFromDb);
+            if (deleteFromDb) {
+                LauncherModel.deleteItemFromDatabase(this, widgetInfo);
+            }
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Unbinds any launcher references to the folder.
+     */
+    private void unbindFolder(FolderInfo folder) {
         sFolders.remove(folder.id);
     }
 
+    /**
+     * Unbinds any launcher references to the widget and deletes the app widget id.
+     */
+    private void unbindAppWidget(final LauncherAppWidgetInfo widgetInfo, boolean deleteAppWidgetId) {
+        final LauncherAppWidgetHost appWidgetHost = getAppWidgetHost();
+        if (deleteAppWidgetId && appWidgetHost != null &&
+                !widgetInfo.isCustomWidget() && widgetInfo.isWidgetIdValid()) {
+            // Deleting an app widget ID is a void call but writes to disk before returning
+            // to the caller...
+            new AsyncTask<Void, Void, Void>() {
+                public Void doInBackground(Void ... args) {
+                    appWidgetHost.deleteAppWidgetId(widgetInfo.appWidgetId);
+                    return null;
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        }
+        removeWidgetToAutoAdvance(widgetInfo.hostView);
+        widgetInfo.hostView = null;
+    }
+
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
         if (event.getAction() == KeyEvent.ACTION_DOWN) {
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index b5922c6..ee5f9ca 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1068,8 +1068,6 @@
 
     /**
      * Removes the specified item from the database
-     * @param context
-     * @param item
      */
     public static void deleteItemFromDatabase(Context context, final ItemInfo item) {
         ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
@@ -1079,8 +1077,6 @@
 
     /**
      * Removes the specified items from the database
-     * @param context
-     * @param item
      */
     static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
         final ContentResolver cr = context.getContentResolver();
@@ -1171,9 +1167,9 @@
     }
 
     /**
-     * Remove the contents of the specified folder from the database
+     * Remove the specified folder and all its contents from the database.
      */
-    public static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
+    public static void deleteFolderAndContentsFromDatabase(Context context, final FolderInfo info) {
         final ContentResolver cr = context.getContentResolver();
 
         Runnable r = new Runnable() {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index b7d7c62..cb064c0 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1118,9 +1118,9 @@
                     LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
                     LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView;
                     if (lahv != null && lahv.isReinflateRequired()) {
-                        mLauncher.removeAppWidget(info);
-                        // Remove the current widget which is inflated with the wrong orientation
-                        cl.removeView(lahv);
+                        // Remove and rebind the current widget (which was inflated in the wrong
+                        // orientation), but don't delete it from the database
+                        mLauncher.removeItem(lahv, info, false  /* deleteFromDb */);
                         mLauncher.bindAppWidget(info);
                     }
                 }
@@ -4523,12 +4523,9 @@
 
             for (LauncherAppWidgetInfo info : mInfos) {
                 if (info.hostView instanceof PendingAppWidgetHostView) {
+                    // Remove and rebind the current widget, but don't delete it from the database
                     PendingAppWidgetHostView view = (PendingAppWidgetHostView) info.hostView;
-                    mLauncher.removeAppWidget(info);
-
-                    CellLayout cl = (CellLayout) view.getParent().getParent();
-                    // Remove the current widget
-                    cl.removeView(view);
+                    mLauncher.removeItem(view, info, false /* deleteFromDb */);
                     mLauncher.bindAppWidget(info);
                 }
             }