Adding drag target bar.

Change-Id: Ia00ed30264ea5f1d3c919111d15588ef441bfe20
diff --git a/src/com/android/launcher2/ApplicationInfoDropTarget.java b/src/com/android/launcher2/ApplicationInfoDropTarget.java
index e02878a..311ac7e 100644
--- a/src/com/android/launcher2/ApplicationInfoDropTarget.java
+++ b/src/com/android/launcher2/ApplicationInfoDropTarget.java
@@ -48,7 +48,7 @@
         super(context, attrs, defStyle);
 
         // Set the hover paint colour
-        int colour = getContext().getResources().getColor(R.color.app_info_filter);
+        int colour = getContext().getResources().getColor(R.color.info_target_hover_tint);
         mHoverPaint.setColorFilter(new PorterDuffColorFilter(colour, PorterDuff.Mode.SRC_ATOP));
 
         if (LauncherApplication.isScreenLarge()) {
diff --git a/src/com/android/launcher2/DeleteDropTarget.java b/src/com/android/launcher2/DeleteDropTarget.java
new file mode 100644
index 0000000..5c67793
--- /dev/null
+++ b/src/com/android/launcher2/DeleteDropTarget.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 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.launcher2;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.TransitionDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher.R;
+
+public class DeleteDropTarget extends IconDropTarget {
+
+    private static final int sTransitionDuration = 0;
+
+    private TransitionDrawable mIcon;
+    private int mDefaultTextColor;
+    private int mHoverColor = 0xFFFF0000;
+
+    public DeleteDropTarget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // Get the drawable
+        mIcon = (TransitionDrawable) getCompoundDrawables()[0];
+
+        // Get the hover color
+        Resources r = getResources();
+        mDefaultTextColor = getTextColors().getDefaultColor();
+        mHoverColor = r.getColor(R.color.delete_target_hover_tint);
+        mHoverPaint.setColorFilter(new PorterDuffColorFilter(
+                mHoverColor, PorterDuff.Mode.SRC_ATOP));
+    }
+
+    private boolean isAllAppsApplication(DragSource source, Object info) {
+        return (source instanceof AppsCustomizePagedView) && (info instanceof ApplicationInfo);
+    }
+    private boolean isAllAppsWidget(DragSource source, Object info) {
+        return (source instanceof AppsCustomizePagedView) && (info instanceof PendingAddWidgetInfo);
+    }
+    private boolean isWorkspaceApplication(DragObject d) {
+        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof ShortcutInfo);
+    }
+    private boolean isWorkspaceWidget(DragObject d) {
+        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof LauncherAppWidgetInfo);
+    }
+    private boolean isWorkspaceFolder(DragObject d) {
+        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo);
+    }
+
+    @Override
+    public boolean acceptDrop(DragObject d) {
+        // We can remove everything including App shortcuts, folders, widgets, etc.
+        return true;
+    }
+
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        ItemInfo item = (ItemInfo) info;
+        boolean isVisible = true;
+        boolean isUninstall = false;
+
+        // If we are dragging a widget from AppsCustomize , hide the delete target
+        if (isAllAppsWidget(source, info)) {
+            isVisible = false;
+        }
+
+        // If we are dragging an application from AppsCustomize, only show the control if we can
+        // delete the app (it was downloaded), and rename the string to "uninstall" in such a case
+        if (isAllAppsApplication(source, info)) {
+            ApplicationInfo appInfo = (ApplicationInfo) info;
+            if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) {
+                isUninstall = true;
+            } else {
+                isVisible = false;
+            }
+        }
+
+        mActive = isVisible;
+        ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
+        if (getText().length() > 0) {
+            setText(isUninstall ? R.string.delete_target_uninstall_label
+                : R.string.delete_target_label);
+        }
+    }
+
+    @Override
+    public void onDragEnd() {
+        super.onDragEnd();
+        mActive = false;
+    }
+
+    public void onDragEnter(DragObject d) {
+        super.onDragEnter(d);
+
+        mIcon.startTransition(sTransitionDuration);
+        setTextColor(mHoverColor);
+    }
+
+    public void onDragExit(DragObject d) {
+        super.onDragExit(d);
+
+        mIcon.reverseTransition(sTransitionDuration);
+        setTextColor(mDefaultTextColor);
+    }
+
+    public void onDrop(DragObject d) {
+        ItemInfo item = (ItemInfo) d.dragInfo;
+
+        if (isAllAppsApplication(d.dragSource, item)) {
+            // Uninstall the application if it is being dragged from AppsCustomize
+            mLauncher.startApplicationUninstallActivity((ApplicationInfo) item);
+        } else if (isWorkspaceApplication(d)) {
+            LauncherModel.deleteItemFromDatabase(mLauncher, item);
+        } else if (isWorkspaceFolder(d)) {
+            // Remove the folder from the workspace and delete the contents from launcher model
+            FolderInfo folderInfo = (FolderInfo) item;
+            mLauncher.removeFolder(folderInfo);
+            LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
+        } else if (isWorkspaceWidget(d)) {
+            // Remove the widget from the workspace
+            mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
+            LauncherModel.deleteItemFromDatabase(mLauncher, item);
+
+            final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
+            final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
+            if (appWidgetHost != null) {
+                // Deleting an app widget ID is a void call but writes to disk before returning
+                // to the caller...
+                new Thread("deleteAppWidgetId") {
+                    public void run() {
+                        appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
+                    }
+                }.start();
+            }
+        }
+    }
+}
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index 21b1cf1..c349e5d 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -62,7 +62,7 @@
     public DeleteZone(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        final int srcColor = context.getResources().getColor(R.color.delete_color_filter);
+        final int srcColor = context.getResources().getColor(R.color.delete_target_hover_tint);
         mHoverPaint.setColorFilter(new PorterDuffColorFilter(srcColor, PorterDuff.Mode.SRC_ATOP));
 
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeleteZone, defStyle, 0);
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 7503dda..af47bea 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -58,7 +58,8 @@
         setMotionEventSplittingEnabled(false);
     }
 
-    public void setDragController(DragController controller) {
+    public void setup(Launcher launcher, DragController controller) {
+        mLauncher = launcher;
         mDragController = controller;
     }
     
@@ -252,10 +253,6 @@
         resizeFrame.snapToWidget(false);
     }
 
-    public void setLauncher(Launcher l) {
-        mLauncher = l;
-    }
-
     public void setCurrentFolder(Folder f) {
         mCurrentFolder = f;
     }
diff --git a/src/com/android/launcher2/InfoDropTarget.java b/src/com/android/launcher2/InfoDropTarget.java
new file mode 100644
index 0000000..bbde2b8
--- /dev/null
+++ b/src/com/android/launcher2/InfoDropTarget.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 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.launcher2;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.launcher.R;
+
+public class InfoDropTarget extends IconDropTarget {
+
+    private int mDefaultTextColor;
+    private int mHoverColor = 0xFF0000FF;
+
+    public InfoDropTarget(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public InfoDropTarget(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // Get the hover color
+        Resources r = getResources();
+        mDefaultTextColor = getTextColors().getDefaultColor();
+        mHoverColor = r.getColor(R.color.info_target_hover_tint);
+        mHoverPaint.setColorFilter(new PorterDuffColorFilter(
+                mHoverColor, PorterDuff.Mode.SRC_ATOP));
+    }
+
+    private boolean isApplication(Object info) {
+        if (info instanceof ApplicationInfo) return true;
+        return (((ItemInfo) info).itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION);
+    }
+
+    @Override
+    public boolean acceptDrop(DragObject d) {
+        // acceptDrop is called just before onDrop. We do the work here, rather than
+        // in onDrop, because it allows us to reject the drop (by returning false)
+        // so that the object being dragged isn't removed from the drag source.
+        ComponentName componentName = null;
+        if (d.dragInfo instanceof ApplicationInfo) {
+            componentName = ((ApplicationInfo) d.dragInfo).componentName;
+        } else if (d.dragInfo instanceof ShortcutInfo) {
+            componentName = ((ShortcutInfo) d.dragInfo).intent.getComponent();
+        }
+        if (componentName != null) {
+            mLauncher.startApplicationDetailsActivity(componentName);
+        }
+        return false;
+    }
+
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        ItemInfo item = (ItemInfo) info;
+        boolean isVisible = true;
+
+        // If we are dragging a widget or shortcut, hide the info target
+        if (!isApplication(info)) {
+            isVisible = false;
+        }
+
+        mActive = isVisible;
+        ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void onDragEnd() {
+        super.onDragEnd();
+        mActive = false;
+    }
+
+    public void onDragEnter(DragObject d) {
+        super.onDragEnter(d);
+
+        setTextColor(mHoverColor);
+    }
+
+    public void onDragExit(DragObject d) {
+        super.onDragExit(d);
+
+        setTextColor(mDefaultTextColor);
+    }
+}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 5cf8e9c..c3d0eea 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -199,6 +199,7 @@
 
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
+    private SearchDropTargetBar mSearchDeleteBar;
     private AllAppsView mAllAppsGrid;
     private AppsCustomizeTabHost mAppsCustomizeTabHost;
     private AppsCustomizePagedView mAppsCustomizeContent;
@@ -896,128 +897,110 @@
     private void setupViews() {
         final DragController dragController = mDragController;
 
-        DragLayer dragLayer = (DragLayer) findViewById(R.id.drag_layer);
-        dragLayer.setDragController(dragController);
-        dragLayer.setLauncher(this);
-        mDragLayer = dragLayer;
+        mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
+        mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
 
+        // Setup the drag layer
+        mDragLayer.setup(this, dragController);
+
+        // Setup the workspace
+        mWorkspace.setHapticFeedbackEnabled(false);
+        mWorkspace.setOnLongClickListener(this);
+        mWorkspace.setup(this, dragController);
+        mWorkspace.setWallpaperDimension();
+
+        // Setup the different configurations
+        DeleteZone allAppsDeleteZone = null;
+        ApplicationInfoDropTarget allAppsInfoTarget = null;
         if (LauncherApplication.isScreenLarge()) {
-            mAllAppsGrid = (AllAppsView) dragLayer.findViewById(R.id.all_apps_view);
+            // Setup AllApps
+            mAllAppsGrid = (AllAppsView) mDragLayer.findViewById(R.id.all_apps_view);
             mAllAppsGrid.setup(this, dragController);
             // We don't want a hole punched in our window.
             ((View) mAllAppsGrid).setWillNotDraw(false);
-        } else {
-            mAppsCustomizeTabHost = (AppsCustomizeTabHost)
-                    findViewById(R.id.apps_customize_pane);
-            mAppsCustomizeContent = (AppsCustomizePagedView)
-                    mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
-            mAppsCustomizeContent.setup(this, dragController);
-        }
 
-        mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
-
-        final Workspace workspace = mWorkspace;
-        workspace.setHapticFeedbackEnabled(false);
-
-        DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone);
-        mDeleteZone = deleteZone;
-
-        View handleView = findViewById(R.id.all_apps_button);
-        if (handleView != null && handleView instanceof HandleView) {
-            // we don't use handle view in xlarge mode
-            mHandleView = (HandleView)handleView;
-            mHandleView.setLauncher(this);
-            mHandleView.setOnLongClickListener(this);
-        }
-
-        if (mCustomizePagedView != null) {
+            // Setup Customize
             mCustomizePagedView.setLauncher(this);
             mCustomizePagedView.setDragController(dragController);
             mCustomizePagedView.setAllAppsPagedView(mAllAppsPagedView);
-        } else {
-             ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
-             hotseatLeft.setContentDescription(mHotseatLabels[0]);
-             hotseatLeft.setImageDrawable(mHotseatIcons[0]);
-             ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
-             hotseatRight.setContentDescription(mHotseatLabels[1]);
-             hotseatRight.setImageDrawable(mHotseatIcons[1]);
 
-             View.OnKeyListener listener = new IndicatorKeyEventListener();
-             mPreviousView = (ImageView) dragLayer.findViewById(R.id.previous_screen);
-             mPreviousView.setOnKeyListener(listener);
-             mNextView = (ImageView) dragLayer.findViewById(R.id.next_screen);
-             mNextView.setOnKeyListener(listener);
+            // Setup DeleteZone
+            mDeleteZone = (DeleteZone) mDragLayer.findViewById(R.id.delete_zone);
+            mDeleteZone.setLauncher(this);
+            mDeleteZone.setDragController(dragController);
 
-             Drawable previous = mPreviousView.getDrawable();
-             Drawable next = mNextView.getDrawable();
-             mWorkspace.setIndicators(previous, next);
+            // Setup the top-right Apps/Customize buttons
+            mAllAppsButton = findViewById(R.id.all_apps_button);
+            mDivider = findViewById(R.id.all_apps_divider);
+            mConfigureButton = findViewById(R.id.configure_button);
+            mDeleteZone.setOverlappingViews(new View[] { mAllAppsButton, mDivider,
+                    mConfigureButton });
 
-             mPreviousView.setHapticFeedbackEnabled(false);
-             mPreviousView.setOnLongClickListener(this);
-             mNextView.setHapticFeedbackEnabled(false);
-             mNextView.setOnLongClickListener(this);
-        }
-
-        workspace.setOnLongClickListener(this);
-        workspace.setDragController(dragController);
-        workspace.setLauncher(this);
-        workspace.setWallpaperDimension();
-
-        deleteZone.setLauncher(this);
-        deleteZone.setDragController(dragController);
-
-        final View allAppsButton = findViewById(R.id.all_apps_button);
-        final View divider = findViewById(R.id.all_apps_divider);
-        final View configureButton = findViewById(R.id.configure_button);
-
-        if (LauncherApplication.isScreenLarge()) {
-            deleteZone.setOverlappingViews(new View[] { allAppsButton, divider, configureButton });
-        } else {
-            deleteZone.setOverlappingView(findViewById(R.id.all_apps_button_cluster));
-        }
-        dragController.addDragListener(deleteZone);
-
-        DeleteZone allAppsDeleteZone = (DeleteZone) findViewById(R.id.all_apps_delete_zone);
-        if (allAppsDeleteZone != null) {
+            // Setup the AllApps Delete toolbar button
+            allAppsDeleteZone = (DeleteZone) findViewById(R.id.all_apps_delete_zone);
             allAppsDeleteZone.setLauncher(this);
             allAppsDeleteZone.setDragController(dragController);
             allAppsDeleteZone.setDragAndDropEnabled(false);
-            dragController.addDragListener(allAppsDeleteZone);
-            dragController.addDropTarget(allAppsDeleteZone);
-        }
 
-        ApplicationInfoDropTarget allAppsInfoTarget = (ApplicationInfoDropTarget)
-                findViewById(R.id.all_apps_info_target);
-        if (allAppsInfoTarget != null) {
+            // Setup the AllApps Info toolbar button
+            allAppsInfoTarget = (ApplicationInfoDropTarget) findViewById(R.id.all_apps_info_target);
             allAppsInfoTarget.setLauncher(this);
-            dragController.addDragListener(allAppsInfoTarget);
             allAppsInfoTarget.setDragAndDropEnabled(false);
-        }
-        View marketButton = findViewById(R.id.market_button);
-        if (marketButton != null) {
-            if (allAppsInfoTarget != null) {
-                allAppsInfoTarget.setOverlappingView(marketButton);
-            }
+
+            // Setup the AllApps Market toolbar button
+            View marketButton = findViewById(R.id.market_button);
+            allAppsInfoTarget.setOverlappingView(marketButton);
             marketButton.setOnClickListener(new OnClickListener() {
                 public void onClick(View v) {
                     onClickAppMarketButton(v);
                 }
             });
+        } else {
+            // Get the search/delete bar
+            mSearchDeleteBar = (SearchDropTargetBar) mDragLayer.findViewById(R.id.qsb_bar);
+
+            // Setup AppsCustomize
+            mAppsCustomizeTabHost = (AppsCustomizeTabHost)
+                    findViewById(R.id.apps_customize_pane);
+            mAppsCustomizeContent = (AppsCustomizePagedView)
+                    mAppsCustomizeTabHost.findViewById(R.id.apps_customize_pane_content);
+            mAppsCustomizeContent.setup(this, dragController);
+
+            // Setup AppsCustomize button
+            mHandleView = (HandleView) mDragLayer.findViewById(R.id.all_apps_button);
+            mHandleView.setLauncher(this);
+            mHandleView.setOnLongClickListener(this);
+            mHandleView.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    onClickAllAppsButton(v);
+                }
+            });
+
+            // Setup Hotseat
+            ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
+            hotseatLeft.setContentDescription(mHotseatLabels[0]);
+            hotseatLeft.setImageDrawable(mHotseatIcons[0]);
+            ImageView hotseatRight = (ImageView) findViewById(R.id.hotseat_right);
+            hotseatRight.setContentDescription(mHotseatLabels[1]);
+            hotseatRight.setImageDrawable(mHotseatIcons[1]);
+
+            View.OnKeyListener listener = new IndicatorKeyEventListener();
+            mPreviousView = (ImageView) mDragLayer.findViewById(R.id.previous_screen);
+            mPreviousView.setOnKeyListener(listener);
+            mNextView = (ImageView) mDragLayer.findViewById(R.id.next_screen);
+            mNextView.setOnKeyListener(listener);
+
+            Drawable previous = mPreviousView.getDrawable();
+            Drawable next = mNextView.getDrawable();
+            mWorkspace.setIndicators(previous, next);
+
+            mPreviousView.setHapticFeedbackEnabled(false);
+            mPreviousView.setOnLongClickListener(this);
+            mNextView.setHapticFeedbackEnabled(false);
+            mNextView.setOnLongClickListener(this);
         }
 
-        dragController.setDragScoller(workspace);
-        dragController.setScrollView(dragLayer);
-        dragController.setMoveTarget(workspace);
-
-        // The order here is bottom to top.
-        dragController.addDropTarget(workspace);
-        dragController.addDropTarget(deleteZone);
-        if (allAppsInfoTarget != null) {
-            dragController.addDropTarget(allAppsInfoTarget);
-        }
-        if (allAppsDeleteZone != null) {
-            dragController.addDropTarget(allAppsDeleteZone);
-        }
+        // Setup keylistener for button cluster
         mButtonCluster = (ViewGroup) findViewById(R.id.all_apps_button_cluster);
         View.OnKeyListener listener = null;
         if (LauncherApplication.isScreenLarge()) {
@@ -1032,33 +1015,25 @@
             mButtonCluster.getChildAt(i).setOnKeyListener(listener);
         }
 
-        mAllAppsButton = findViewById(R.id.all_apps_button);
-        mDivider = findViewById(R.id.all_apps_divider);
-        mConfigureButton = findViewById(R.id.configure_button);
-
-        // We had previously set these click handlers in XML, but the first time we launched
-        // Configure or All Apps we had an extra 50ms of delay while the java reflection methods
-        // found the right handler. Setting the handlers directly here eliminates that cost.
-        if (mConfigureButton != null) {
-            mConfigureButton.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    onClickConfigureButton(v);
-                }
-            });
+        // Setup the drag controller (the drop targets have to be added in reverse order)
+        dragController.setDragScoller(mWorkspace);
+        dragController.setScrollView(mDragLayer);
+        dragController.setMoveTarget(mWorkspace);
+        dragController.addDropTarget(mWorkspace);
+        if (mDeleteZone != null) {
+            dragController.addDragListener(mDeleteZone);
+            dragController.addDropTarget(mDeleteZone);
         }
-        if (mDivider != null) {
-            mDivider.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    onClickAllAppsButton(v);
-                }
-            });
+        if (mSearchDeleteBar != null) {
+            mSearchDeleteBar.setup(this, dragController);
         }
-        if (mAllAppsButton != null) {
-            mAllAppsButton.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    onClickAllAppsButton(v);
-                }
-            });
+        if (allAppsDeleteZone != null) {
+            dragController.addDragListener(allAppsDeleteZone);
+            dragController.addDropTarget(allAppsDeleteZone);
+        }
+        if (allAppsInfoTarget != null) {
+            dragController.addDragListener(allAppsInfoTarget);
+            dragController.addDropTarget(allAppsInfoTarget);
         }
     }
 
@@ -2613,22 +2588,30 @@
         switch (newState) {
         case WORKSPACE:
             hideOrShowToolbarButton(true, mButtonCluster, showSeq);
-            mDeleteZone.setDragAndDropEnabled(true);
-            if (LauncherApplication.isScreenLarge()) {
-                mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_workspace));
+            if (mDeleteZone != null) {
+                mDeleteZone.setDragAndDropEnabled(true);
+                if (LauncherApplication.isScreenLarge()) {
+                    mDeleteZone.setText(
+                            getResources().getString(R.string.delete_zone_label_workspace));
+                }
             }
             break;
         case ALL_APPS:
         case APPS_CUSTOMIZE:
             hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
-            mDeleteZone.setDragAndDropEnabled(false);
-            if (LauncherApplication.isScreenLarge()) {
-                mDeleteZone.setText(getResources().getString(R.string.delete_zone_label_all_apps));
+            if (mDeleteZone != null) {
+                mDeleteZone.setDragAndDropEnabled(false);
+                if (LauncherApplication.isScreenLarge()) {
+                    mDeleteZone.setText(
+                            getResources().getString(R.string.delete_zone_label_all_apps));
+                }
             }
             break;
         case CUSTOMIZE:
             hideOrShowToolbarButton(false, mButtonCluster, hideSeq);
-            mDeleteZone.setDragAndDropEnabled(false);
+            if (mDeleteZone != null) {
+                mDeleteZone.setDragAndDropEnabled(false);
+            }
             break;
         }
     }
@@ -2960,8 +2943,9 @@
             cameraZoomOut(State.ALL_APPS, animated, false);
             ((View) mAllAppsGrid).requestFocus();
 
-            // TODO: fade these two too
-            mDeleteZone.setVisibility(View.GONE);
+            if (mDeleteZone != null) {
+                mDeleteZone.setVisibility(View.GONE);
+            }
 
             // Change the state *after* we've called all the transition code
             mState = State.ALL_APPS;
diff --git a/src/com/android/launcher2/SearchDropTargetBar.java b/src/com/android/launcher2/SearchDropTargetBar.java
new file mode 100644
index 0000000..7a208b7
--- /dev/null
+++ b/src/com/android/launcher2/SearchDropTargetBar.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 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.launcher2;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.launcher.R;
+
+/*
+ * Ths bar will manage the transition between the QSB search bar and the delete drop
+ * targets so that each of the individual IconDropTargets don't have to.
+ */
+public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener {
+
+    private static final int sTransitionInDuration = 275;
+    private static final int sTransitionOutDuration = 200;
+
+    private View mQSBSearchBar;
+    private View mDropTargetBar;
+    private IconDropTarget mInfoDropTarget;
+    private IconDropTarget mDeleteDropTarget;
+
+    public SearchDropTargetBar(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public SearchDropTargetBar(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void setup(Launcher launcher, DragController dragController) {
+        dragController.addDragListener(this);
+        dragController.addDragListener(mInfoDropTarget);
+        dragController.addDragListener(mDeleteDropTarget);
+        dragController.addDropTarget(mInfoDropTarget);
+        dragController.addDropTarget(mDeleteDropTarget);
+        mInfoDropTarget.setLauncher(launcher);
+        mDeleteDropTarget.setLauncher(launcher);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        // Get the individual components
+        mQSBSearchBar = findViewById(R.id.qsb_search_bar);
+        mDropTargetBar = findViewById(R.id.drag_target_bar);
+        mInfoDropTarget = (IconDropTarget) mDropTargetBar.findViewById(R.id.info_target);
+        mDeleteDropTarget = (IconDropTarget) mDropTargetBar.findViewById(R.id.delete_target);
+    }
+
+    /*
+     * DragController.DragListener implementation
+     */
+    @Override
+    public void onDragStart(DragSource source, Object info, int dragAction) {
+        // Animate out the QSB search bar, and animate in the drop target bar
+        mQSBSearchBar.animate().alpha(0f).setDuration(sTransitionOutDuration);
+        mDropTargetBar.animate().alpha(1f).setDuration(sTransitionInDuration);
+    }
+
+    @Override
+    public void onDragEnd() {
+        // Restore the QSB search bar, and animate out the drop target bar
+        mDropTargetBar.animate().alpha(0f).setDuration(sTransitionOutDuration);
+        mQSBSearchBar.animate().alpha(1f).setDuration(sTransitionInDuration);
+    }
+}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 7d2626d..b05bd49 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -3233,7 +3233,7 @@
                 pixelX, pixelY, spanX, spanY, recycle);
     }
 
-    void setLauncher(Launcher launcher) {
+    void setup(Launcher launcher, DragController dragController) {
         mLauncher = launcher;
         mSpringLoadedDragController = new SpringLoadedDragController(mLauncher);
 
@@ -3242,9 +3242,6 @@
             mCustomizationDrawerContent =
                 mCustomizationDrawer.findViewById(com.android.internal.R.id.tabcontent);
         }
-    }
-
-    public void setDragController(DragController dragController) {
         mDragController = dragController;
     }