Adding drag target bar.

Change-Id: Ia00ed30264ea5f1d3c919111d15588ef441bfe20
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index c8a82e6..7073661 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -87,20 +87,6 @@
         android:focusable="true"
         android:clickable="true" />
 
-    <com.android.launcher2.DeleteZone
-        android:id="@+id/delete_zone"
-        android:layout_width="@dimen/delete_zone_size"
-        android:layout_height="@dimen/delete_zone_size"
-        android:paddingLeft="@dimen/delete_zone_padding"
-        android:layout_marginBottom="@dimen/half_status_bar_height"
-        android:layout_gravity="right|center_vertical"
-
-        android:scaleType="center"
-        android:drawableLeft="@drawable/delete_zone_selector"
-        android:visibility="invisible"
-        launcher:direction="vertical"
-        />
-
     <RelativeLayout
         android:id="@+id/all_apps_button_cluster"
         android:layout_height="fill_parent"
diff --git a/res/layout-large/button_bar.xml b/res/layout-large/button_bar.xml
index 62115f7..a060761 100644
--- a/res/layout-large/button_bar.xml
+++ b/res/layout-large/button_bar.xml
@@ -71,6 +71,7 @@
     <!-- AllApps icon -->
     <com.android.launcher2.StrokedTextView
         android:id="@+id/all_apps_button"
+        android:onClick="onClickAllAppsButton"
         android:text="@string/all_apps_button_label"
         android:drawablePadding="@dimen/all_apps_button_drawable_padding"
         android:drawableLeft="@drawable/ic_home_all_apps_holo_dark"
@@ -103,6 +104,7 @@
     <ImageView
         android:id="@+id/all_apps_divider"
         android:src="@drawable/divider_launcher_holo"
+        android:onClick="onClickAllAppsButton"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_toLeftOf="@+id/configure_button"
@@ -116,6 +118,7 @@
     <ImageView
         android:id="@+id/configure_button"
         android:src="@drawable/ic_home_add_holo_dark"
+        android:onClick="onClickConfigureButton"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
@@ -141,7 +144,7 @@
         android:paddingRight="@dimen/toolbar_button_horizontal_padding"
         android:paddingTop="@dimen/toolbar_button_vertical_padding"
         android:paddingBottom="@dimen/toolbar_button_vertical_padding"
-       android:background="@drawable/button_bg"
+        android:background="@drawable/button_bg"
 
         android:gravity="center_horizontal|center_vertical"
         android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index f05f9b6..2d5a34f 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -80,19 +80,6 @@
         android:focusable="true"
         android:clickable="true" />
 
-    <com.android.launcher2.DeleteZone
-        android:id="@+id/delete_zone"
-        android:layout_width="@dimen/delete_zone_size"
-        android:layout_height="@dimen/delete_zone_size"
-        android:paddingTop="@dimen/delete_zone_padding"
-        android:layout_gravity="bottom|center_horizontal"
-
-        android:scaleType="center"
-        android:drawableLeft="@drawable/delete_zone_selector"
-        android:visibility="invisible"
-        launcher:direction="horizontal"
-        />
-
     <RelativeLayout
         android:id="@+id/all_apps_button_cluster"
         android:layout_width="fill_parent"
diff --git a/res/layout/qsb_bar.xml b/res/layout/qsb_bar.xml
index 5469224..820fae6 100644
--- a/res/layout/qsb_bar.xml
+++ b/res/layout/qsb_bar.xml
@@ -13,17 +13,17 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<FrameLayout
+<com.android.launcher2.SearchDropTargetBar
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
     android:focusable="false">
 
     <!-- Search buttons container -->
     <LinearLayout
+        style="@style/SearchDropTargetBar"
         android:id="@+id/qsb_search_bar"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        style="@style/SearchBar">
+        android:layout_height="match_parent">
        <!-- Global search icon -->
        <ImageView
             style="@style/SearchButton"
@@ -61,10 +61,32 @@
 
     <!-- Drag specific targets container -->
     <LinearLayout
+        style="@style/SearchDropTargetBar"
         android:id="@+id/drag_target_bar"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="#FF00FF00"
-        android:visibility="gone">
+        android:alpha="0">
+
+        <FrameLayout
+            style="@style/DropTargetButtonContainer"
+            android:layout_weight="1">
+            <!-- Delete target -->
+            <com.android.launcher2.DeleteDropTarget
+                style="@style/DropTargetButton"
+                android:id="@+id/delete_target"
+                android:text="@string/delete_zone_label_workspace"
+                android:drawableLeft="@drawable/delete_zone_selector" />
+        </FrameLayout>
+
+        <FrameLayout
+            style="@style/DropTargetButtonContainer"
+            android:layout_weight="1">
+            <!-- Info target -->
+            <com.android.launcher2.InfoDropTarget
+                style="@style/DropTargetButton"
+                android:id="@+id/info_target"
+                android:text="@string/info_target_label"
+                android:drawableLeft="@drawable/ic_home_info_holo_dark" />
+        </FrameLayout>
     </LinearLayout>
-</FrameLayout>
+</com.android.launcher2.SearchDropTargetBar>
diff --git a/res/values-land/strings.xml b/res/values-land/strings.xml
new file mode 100644
index 0000000..bbe8ff2
--- /dev/null
+++ b/res/values-land/strings.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Manifest configuration. -->
+    <skip />
+
+    <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+    <string name="delete_target_label"></string>
+    <!-- Label for uninstall drop target. [CHAR_LIMIT=30]-->
+    <string name="delete_target_uninstall_label"></string>
+    <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+    <string name="info_target_label"></string>
+</resources>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index 50aba09..4daaecc 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -19,7 +19,7 @@
 
 <resources>
 <!-- Search Bar -->
-    <style name="SearchBar">
+    <style name="SearchDropTargetBar">
         <item name="android:orientation">vertical</item>
     </style>
     <style name="SearchButton">
@@ -34,6 +34,20 @@
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_gravity">center_horizontal</item>
     </style>
+    <style name="DropTargetButtonContainer">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">0dp</item>
+    </style>
+    <style name="DropTargetButton">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:layout_gravity">center_vertical</item>
+        <item name="android:gravity">center_horizontal</item>
+        <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
+        <item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
+    </style>
 
     <style name="HotseatButton">
         <item name="android:paddingTop">12dip</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6c372e3..e14fbfe 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -18,10 +18,14 @@
 */
 -->
 <resources>
+    <!-- The color tints to apply to the text and drag view when hovering
+         over the delete target or the info target -->
+    <color name="delete_target_hover_tint">#A5FF0000</color>
+    <color name="info_target_hover_tint">#A50000FE</color>
+
     <color name="window_background">#FF191919</color>
     <color name="grid_dark_background">#EB191919</color>     
     <color name="bubble_dark_background">#20000000</color>
-    <color name="delete_color_filter">#A5FF0000</color>
 
     <color name="appwidget_error_color">#FCCC</color>
     <color name="snag_callout_color">#F444</color>
@@ -29,7 +33,6 @@
     <color name="gesture_color">#ff0563c1</color>
     <color name="uncertain_gesture_color">#ff848484</color>
 
-    <color name="app_info_filter">#A50000FE</color>
     <color name="dimmed_view_color">#FF7F7F7F</color>
 
     <color name="drag_outline_color">#6595f9</color>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 32e649d..e59fd6e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -162,6 +162,13 @@
          device. [CHAR_LIMIT=30]-->
     <string name="delete_zone_label_all_apps">Uninstall</string>
 
+    <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+    <string name="delete_target_label">Remove</string>
+    <!-- Label for uninstall drop target. [CHAR_LIMIT=30]-->
+    <string name="delete_target_uninstall_label">Uninstall</string>
+    <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+    <string name="info_target_label">Manage</string>
+
     <!-- Accessibility: Search button -->
     <string name="accessibility_search_button">Search</string>
     <!-- Accessibility: Voice Search button -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c3e6ce9..36a4be0 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -68,7 +68,7 @@
         <item name="android:layout_marginRight">10dip</item>
     </style>
 
-    <style name="SearchBar">
+    <style name="SearchDropTargetBar">
         <item name="android:orientation">horizontal</item>
     </style>
     <style name="SearchButton">
@@ -83,7 +83,19 @@
         <item name="android:layout_height">match_parent</item>
         <item name="android:layout_gravity">center_vertical</item>
     </style>
-
+    <style name="DropTargetButtonContainer">
+        <item name="android:layout_width">0dp</item>
+        <item name="android:layout_height">match_parent</item>
+    </style>
+    <style name="DropTargetButton">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">match_parent</item>
+        <item name="android:layout_gravity">center_horizontal</item>
+        <item name="android:gravity">center_vertical</item>
+        <item name="android:drawablePadding">7.5dp</item>
+        <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
+        <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
+    </style>
 
     <style name="TabIndicator">
         <item name="android:layout_width">wrap_content</item>
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;
     }