Add undo snackbar for deleting items

- Add methods to ModelWriter to prepareForUndoDelete, then
  enqueueDeleteRunnable, followed by commitDelete or abortDelete.
- Add Snackbar floating view
- Show Undo snackbar when dropping or flinging to delete target; if the
  undo action is clicked, we abort the delete, otherwise we commit it.

Bug: 24238108
Change-Id: I9997235e1f8525cbb8b1fa2338099609e7358426
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 64a58fb..c80f96b 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -23,10 +23,11 @@
 
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.dragndrop.DragOptions;
-import com.android.launcher3.folder.Folder;
 import com.android.launcher3.logging.LoggerUtils;
+import com.android.launcher3.model.ModelWriter;
 import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
+import com.android.launcher3.views.Snackbar;
 
 public class DeleteDropTarget extends ButtonDropTarget {
 
@@ -81,13 +82,17 @@
      */
     private void setTextBasedOnDragSource(ItemInfo item) {
         if (!TextUtils.isEmpty(mText)) {
-            mText = getResources().getString(item.id != ItemInfo.NO_ID
+            mText = getResources().getString(canRemove(item)
                     ? R.string.remove_drop_target_label
                     : android.R.string.cancel);
             requestLayout();
         }
     }
 
+    private boolean canRemove(ItemInfo item) {
+        return item.id != ItemInfo.NO_ID;
+    }
+
     /**
      * Set mControlType depending on the drag item.
      */
@@ -97,10 +102,21 @@
     }
 
     @Override
+    public void onDrop(DragObject d, DragOptions options) {
+        if (canRemove(d.dragInfo)) {
+            mLauncher.getModelWriter().prepareToUndoDelete();
+        }
+        super.onDrop(d, options);
+    }
+
+    @Override
     public void completeDrop(DragObject d) {
         ItemInfo item = d.dragInfo;
-        if ((d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder)) {
+        if (canRemove(item)) {
             onAccessibilityDrop(null, item);
+            ModelWriter modelWriter = mLauncher.getModelWriter();
+            Snackbar.show(mLauncher, R.string.item_removed, R.string.undo,
+                    modelWriter::commitDelete, modelWriter::abortDelete);
         }
     }