Improving home screen customization

- Created a drawer with tabs for widgets, folders, shortcuts, wallpapers
(wallpapers are currently not implemented)
- Tapping outside the drawer dismisses it
- Moved the all apps icon to the upper right of the screen
- Adding a toast that says "No more space on screen" when dragging a widget to a full screen
- Fixed bug where you could stack two equal-sized widgets on top of each other on the homescreen (exposed by the new ability to drag widgets onto the home screen)

Change-Id: I03b65ce54a85d24328c94e0c06e249571de449ee
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index d69c56f..1d45565 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -1104,7 +1104,9 @@
 
             boolean found = false;
 
-            if (this.spanX >= spanX && this.spanY >= spanY) {
+            // return the span represented by the CellInfo only there is no view there
+            //   (this.cell == null) and there is enough space
+            if (this.cell == null && this.spanX >= spanX && this.spanY >= spanY) {
                 cellXY[0] = cellX;
                 cellXY[1] = cellY;
                 found = true;
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index c683207..ab71670 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -18,13 +18,13 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.view.MotionEvent;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
 
 /**
- * A ViewGroup that coordinated dragging across its dscendants
+ * A ViewGroup that coordinates dragging across its descendants
  */
 public class DragLayer extends FrameLayout {
     DragController mDragController;
@@ -33,7 +33,7 @@
      * Used to create a new DragLayer from XML.
      *
      * @param context The application's context.
-     * @param attrs The attribtues set containing the Workspace's customization values.
+     * @param attrs The attributes set containing the Workspace's customization values.
      */
     public DragLayer(Context context, AttributeSet attrs) {
         super(context, attrs);
diff --git a/src/com/android/launcher2/FolderChooser.java b/src/com/android/launcher2/FolderChooser.java
new file mode 100644
index 0000000..b152ad5
--- /dev/null
+++ b/src/com/android/launcher2/FolderChooser.java
@@ -0,0 +1,37 @@
+package com.android.launcher2;
+
+import com.android.launcher.R;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.provider.LiveFolders;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.AdapterView;
+
+public class FolderChooser extends HomeCustomizationItemGallery {
+
+    public FolderChooser(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+        // todo: this code sorta overlaps with other places
+        ResolveInfo info = (ResolveInfo)getAdapter().getItem(position);
+        mLauncher.prepareAddItemFromHomeCustomizationDrawer();
+
+        Intent createFolderIntent = new Intent(LiveFolders.ACTION_CREATE_LIVE_FOLDER);
+        if (info.labelRes == R.string.group_folder) {
+            // Create app shortcuts is a special built-in case of shortcuts
+            createFolderIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, getContext().getString(R.string.group_folder));
+        } else {
+            ComponentName name = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+            createFolderIntent.setComponent(name);
+        }
+        mLauncher.addLiveFolder(createFolderIntent);
+
+        return true;
+    }
+}
diff --git a/src/com/android/launcher2/FolderListAdapter.java b/src/com/android/launcher2/FolderListAdapter.java
new file mode 100644
index 0000000..bdfeaeb
--- /dev/null
+++ b/src/com/android/launcher2/FolderListAdapter.java
@@ -0,0 +1,20 @@
+package com.android.launcher2;
+
+import com.android.launcher.R;
+
+import android.content.Context;
+import android.content.pm.ResolveInfo;
+
+public class FolderListAdapter extends IntentListAdapter {
+
+    public FolderListAdapter(Context context, String actionFilter) {
+        super(context, actionFilter);
+
+        // Manually create a separate entry for creating a folder in Launcher
+        ResolveInfo folder = new ResolveInfo();
+        folder.icon = R.drawable.ic_launcher_folder;
+        folder.labelRes = R.string.group_folder;
+        folder.resolvePackageName = context.getPackageName();
+        mIntentList.add(0, folder);
+    }
+}
diff --git a/src/com/android/launcher2/HomeCustomizationItemGallery.java b/src/com/android/launcher2/HomeCustomizationItemGallery.java
new file mode 100644
index 0000000..df64d5e
--- /dev/null
+++ b/src/com/android/launcher2/HomeCustomizationItemGallery.java
@@ -0,0 +1,50 @@
+package com.android.launcher2;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.Gallery;
+
+public abstract class HomeCustomizationItemGallery extends Gallery
+    implements Gallery.OnItemLongClickListener {
+
+    protected Context mContext;
+
+    protected Launcher mLauncher;
+
+    protected int mMotionDownRawX;
+    protected int mMotionDownRawY;
+
+    public HomeCustomizationItemGallery(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setLongClickable(true);
+        setOnItemLongClickListener(this);
+        mContext = context;
+
+        setCallbackDuringFling(false);
+    }
+
+    public void setLauncher(Launcher launcher) {
+        mLauncher = launcher;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (ev.getAction() == MotionEvent.ACTION_DOWN && mLauncher.isAllAppsVisible()) {
+            return false;
+        }
+
+        super.onTouchEvent(ev);
+
+        int x = (int) ev.getX();
+        int y = (int) ev.getY();
+
+        switch (ev.getAction()) {
+        case MotionEvent.ACTION_DOWN:
+            mMotionDownRawX = (int) ev.getRawX();
+            mMotionDownRawY = (int) ev.getRawY();
+        }
+        return true;
+    }
+}
+
diff --git a/src/com/android/launcher2/IntentListAdapter.java b/src/com/android/launcher2/IntentListAdapter.java
new file mode 100644
index 0000000..7ebffd4
--- /dev/null
+++ b/src/com/android/launcher2/IntentListAdapter.java
@@ -0,0 +1,67 @@
+package com.android.launcher2;
+
+import com.android.launcher.R;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.provider.LiveFolders;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.List;
+
+public class IntentListAdapter extends BaseAdapter {
+    private LayoutInflater mLayoutInflater;
+    private PackageManager mPackageManager;
+    protected List<ResolveInfo> mIntentList;
+
+    public IntentListAdapter(Context context, String actionFilter) {
+        mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        mPackageManager = context.getPackageManager();
+
+        Intent createLiveFolderIntent = new Intent(actionFilter);
+        mIntentList = mPackageManager.queryIntentActivities(createLiveFolderIntent, 0);
+    }
+
+    public int getCount() {
+        return mIntentList.size();
+    }
+
+    public Object getItem(int position) {
+        return mIntentList.get(position);
+    }
+
+    public long getItemId(int position) {
+        return position;
+    }
+
+    public View getView(int position, View convertView, ViewGroup parent) {
+        TextView textView;
+
+        if (convertView == null) {
+            textView = (TextView) mLayoutInflater.inflate(
+                    R.layout.home_customization_drawer_item, parent, false);
+        } else {
+            textView = (TextView) convertView;
+        }
+
+        ResolveInfo info = mIntentList.get(position);
+        Drawable image = info.loadIcon(mPackageManager);
+        image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
+        textView.setCompoundDrawables(null, image, null, null);
+
+        CharSequence label = info.loadLabel(mPackageManager);
+        textView.setText(label);
+
+        return textView;
+    }
+}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 69911a7..e413a70 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -16,19 +16,14 @@
 
 package com.android.launcher2;
 
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import com.android.common.Search;
+import com.android.launcher.R;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.SearchManager;
 import android.app.StatusBarManager;
+import android.app.TabActivity;
 import android.app.WallpaperManager;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
@@ -71,27 +66,37 @@
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.View.OnLongClickListener;
+import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
 import android.widget.EditText;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.PopupWindow;
+import android.widget.TabHost;
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.common.Search;
-import com.android.launcher.R;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 
 /**
  * Default launcher application.
  */
-public final class Launcher extends Activity
-        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {
+public final class Launcher extends TabActivity
+        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
+                   AllAppsView.Watcher, View.OnTouchListener {
     static final String TAG = "Launcher";
     static final boolean LOGD = false;
 
@@ -183,7 +188,7 @@
     private DeleteZone mDeleteZone;
     private HandleView mHandleView;
     private AllAppsView mAllAppsGrid;
-    private WidgetChooser mWidgetChooser;
+    private TabHost mHomeCustomizationDrawer;
 
     private Bundle mSavedState;
 
@@ -243,6 +248,22 @@
         setWallpaperDimension();
         setContentView(R.layout.launcher);
 
+        mHomeCustomizationDrawer = getTabHost();
+
+        String widgetsLabel = getString(R.string.widgets_tab_label);
+        mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec("widgets")
+                .setIndicator(widgetsLabel).setContent(R.id.widget_chooser));
+        String foldersLabel = getString(R.string.folders_tab_label);
+        mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec("folders")
+                .setIndicator(foldersLabel).setContent(R.id.folder_chooser));
+        String shortcutsLabel = getString(R.string.shortcuts_tab_label);
+        mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec("shortcuts")
+                .setIndicator(shortcutsLabel).setContent(R.id.shortcut_chooser));
+        String wallpapersLabel = getString(R.string.wallpapers_tab_label);
+        mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec("wallpapers")
+                .setIndicator(wallpapersLabel).setContent(R.id.wallpaperstab));
+
+        mHomeCustomizationDrawer.setCurrentTab(0);
         setupViews();
 
         registerContentObservers();
@@ -562,8 +583,6 @@
                     break;
                 case REQUEST_CREATE_APPWIDGET:
                     int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
-                    // TODO: Is this log message meaningful?
-                    if (LOGD) Log.d(TAG, "dumping extras content=" + data.getExtras());
                     completeAddAppWidget(appWidgetId, mAddItemCellInfo);
                     break;
                 case REQUEST_PICK_WALLPAPER:
@@ -739,6 +758,7 @@
         mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
         final Workspace workspace = mWorkspace;
         workspace.setHapticFeedbackEnabled(false);
+        workspace.setOnInterceptTouchListener(this);
 
         DeleteZone deleteZone = (DeleteZone) dragLayer.findViewById(R.id.delete_zone);
         mDeleteZone = deleteZone;
@@ -748,10 +768,22 @@
         mHandleView.setOnClickListener(this);
         mHandleView.setOnLongClickListener(this);
 
-        mWidgetChooser = (WidgetChooser) findViewById(R.id.widget_chooser);
-        if (mWidgetChooser != null) {
-            mWidgetChooser.setDragController(dragController);
-            mWidgetChooser.setLauncher(this);
+        WidgetChooser widgetChooser = (WidgetChooser) findViewById(R.id.widget_chooser);
+        if (widgetChooser != null) {
+            WidgetListAdapter widgetGalleryAdapter = new WidgetListAdapter(this);
+            widgetChooser.setAdapter(widgetGalleryAdapter);
+            widgetChooser.setDragController(dragController);
+            widgetChooser.setLauncher(this);
+
+            FolderChooser folderChooser = (FolderChooser) findViewById(R.id.folder_chooser);
+            IntentListAdapter folderTypes = new FolderListAdapter(this, LiveFolders.ACTION_CREATE_LIVE_FOLDER);
+            folderChooser.setAdapter(folderTypes);
+            folderChooser.setLauncher(this);
+
+            ShortcutChooser shortcutChooser = (ShortcutChooser) findViewById(R.id.shortcut_chooser);
+            IntentListAdapter shortcutTypes = new ShortcutListAdapter(this, Intent.ACTION_CREATE_SHORTCUT);
+            shortcutChooser.setAdapter(shortcutTypes);
+            shortcutChooser.setLauncher(this);
         } else {
              ImageView hotseatLeft = (ImageView) findViewById(R.id.hotseat_left);
              hotseatLeft.setContentDescription(mHotseatLabels[0]);
@@ -1161,6 +1193,13 @@
         return true;
     }
 
+    // we need to initialize mAddItemCellInfo before adding something to the homescreen -- when
+    // using the settings menu to add an item, something similar happens in showAddDialog
+    public void prepareAddItemFromHomeCustomizationDrawer() {
+        mMenuAddInfo = mWorkspace.findAllVacantCells(null);
+        mAddItemCellInfo = mMenuAddInfo;
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
@@ -1502,6 +1541,29 @@
         }
     }
 
+    private final class SlideDownFinishedListener implements Animation.AnimationListener {
+        TabHost mHomeCustomizationDrawer;
+        SlideDownFinishedListener(TabHost homeCustomizationDrawer) {
+            mHomeCustomizationDrawer = homeCustomizationDrawer;
+        }
+        public void onAnimationEnd(Animation animation) {
+            mHomeCustomizationDrawer.setVisibility(View.GONE);
+        }
+        public void onAnimationRepeat(Animation animation) {}
+        public void onAnimationStart(Animation animation) {}
+    }
+
+    public boolean onTouch(View v, MotionEvent event) {
+        // this is being forwarded from mWorkspace;
+        // clicking anywhere on the workspace causes the drawer to slide down
+        if (mHomeCustomizationDrawer.getVisibility() == View.VISIBLE) {
+            Animation slideDownAnimation = AnimationUtils.loadAnimation(this, R.anim.home_customization_drawer_slide_down);
+            slideDownAnimation.setAnimationListener(new SlideDownFinishedListener(mHomeCustomizationDrawer));
+            mHomeCustomizationDrawer.startAnimation(slideDownAnimation);
+        }
+        return false;
+    }
+
     /**
      * Event handler for the "plus" button that appears on the home screen, which
      * enters home screen customization mode.
@@ -1509,11 +1571,12 @@
      * @param v The view that was clicked.
      */
     public void onClickAddButton(View v) {
-        View widgetChooser = findViewById(R.id.widget_chooser);
-        widgetChooser.setVisibility(View.VISIBLE);
 
         // Animate the widget chooser up from the bottom of the screen
-        widgetChooser.startAnimation(AnimationUtils.loadAnimation(this, R.anim.widget_chooser_slide_up));
+        if (mHomeCustomizationDrawer.getVisibility() == View.GONE) {
+            mHomeCustomizationDrawer.setVisibility(View.VISIBLE);
+            mHomeCustomizationDrawer.startAnimation(AnimationUtils.loadAnimation(this, R.anim.home_customization_drawer_slide_up));
+        }
     }
 
     public void onClickAllAppsButton(View w) {
@@ -1841,6 +1904,7 @@
     }
 
     private void pickShortcut() {
+        // Insert extra item to handle picking application
         Bundle bundle = new Bundle();
 
         ArrayList<String> shortcutNames = new ArrayList<String>();
@@ -2070,7 +2134,6 @@
 
             switch (which) {
                 case AddAdapter.ITEM_SHORTCUT: {
-                    // Insert extra item to handle picking application
                     pickShortcut();
                     break;
                 }
diff --git a/src/com/android/launcher2/ShortcutChooser.java b/src/com/android/launcher2/ShortcutChooser.java
new file mode 100644
index 0000000..1e3e5d0
--- /dev/null
+++ b/src/com/android/launcher2/ShortcutChooser.java
@@ -0,0 +1,37 @@
+package com.android.launcher2;
+
+import com.android.launcher.R;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.AdapterView;
+
+public class ShortcutChooser extends HomeCustomizationItemGallery {
+
+    public ShortcutChooser(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+        // todo: this code sorta overlaps with other places
+        ResolveInfo info = (ResolveInfo)getAdapter().getItem(position);
+        mLauncher.prepareAddItemFromHomeCustomizationDrawer();
+
+        Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
+        if (info.labelRes == R.string.group_applications) {
+            // Create app shortcuts is a special built-in case of shortcuts
+            createShortcutIntent.putExtra(
+                    Intent.EXTRA_SHORTCUT_NAME,getContext().getString(R.string.group_applications));
+        } else {
+            ComponentName name = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+            createShortcutIntent.setComponent(name);
+        }
+        mLauncher.processShortcut(createShortcutIntent);
+
+        return true;
+    }
+}
diff --git a/src/com/android/launcher2/ShortcutListAdapter.java b/src/com/android/launcher2/ShortcutListAdapter.java
new file mode 100644
index 0000000..be05ca4
--- /dev/null
+++ b/src/com/android/launcher2/ShortcutListAdapter.java
@@ -0,0 +1,26 @@
+package com.android.launcher2;
+
+import com.android.launcher.R;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.Intent.ShortcutIconResource;
+import android.content.pm.ResolveInfo;
+
+import java.util.ArrayList;
+
+
+public class ShortcutListAdapter extends IntentListAdapter {
+
+    public ShortcutListAdapter(Context context, String actionFilter) {
+        super(context, actionFilter);
+
+        // Manually create a separate entry for creating an Application shortcut
+        ResolveInfo folder = new ResolveInfo();
+
+        folder.icon = R.drawable.ic_launcher_application;
+        folder.labelRes = R.string.group_applications;
+        folder.resolvePackageName = context.getPackageName();
+        mIntentList.add(0, folder);
+    }
+}
diff --git a/src/com/android/launcher2/WidgetChooser.java b/src/com/android/launcher2/WidgetChooser.java
index fc354d7..4718c6c 100644
--- a/src/com/android/launcher2/WidgetChooser.java
+++ b/src/com/android/launcher2/WidgetChooser.java
@@ -6,52 +6,23 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.view.MotionEvent;
 import android.view.View;
 import android.widget.AdapterView;
-import android.widget.Gallery;
 
-public class WidgetChooser extends Gallery
-    implements Gallery.OnItemLongClickListener, DragSource {
-
-    Context mContext;
-
-    private Launcher mLauncher;
+public class WidgetChooser extends HomeCustomizationItemGallery implements DragSource {
     private DragController mDragController;
-    private WidgetGalleryAdapter mWidgetGalleryAdapter;
-
-    private int mMotionDownRawX;
-    private int mMotionDownRawY;
 
     public WidgetChooser(Context context, AttributeSet attrs) {
         super(context, attrs);
-        setLongClickable(true);
-        setOnItemLongClickListener(this);
-        mContext = context;
-
-        setCallbackDuringFling(false);
-
-        mWidgetGalleryAdapter = new WidgetGalleryAdapter(context);
-        setAdapter(mWidgetGalleryAdapter);
-    }
-
-    public void onDropCompleted(View target, boolean success) {
-        // TODO Auto-generated method stub
-
     }
 
     public void setDragController(DragController dragger) {
         mDragController = dragger;
     }
 
-    public void setLauncher(Launcher launcher) {
-        mLauncher = launcher;
-    }
-
     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
-        AppWidgetProviderInfo info = (AppWidgetProviderInfo)mWidgetGalleryAdapter.getItem(position);
+        AppWidgetProviderInfo info = (AppWidgetProviderInfo)getAdapter().getItem(position);
         try {
             Resources r = mContext.getPackageManager().getResourcesForApplication(info.provider.getPackageName());
 
@@ -73,22 +44,7 @@
         }
     }
 
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_DOWN && mLauncher.isAllAppsVisible()) {
-            return false;
-        }
-
-        super.onTouchEvent(ev);
-
-        int x = (int) ev.getX();
-        int y = (int) ev.getY();
-
-        switch (ev.getAction()) {
-        case MotionEvent.ACTION_DOWN:
-            mMotionDownRawX = (int) ev.getRawX();
-            mMotionDownRawY = (int) ev.getRawY();
-        }
-        return true;
+    public void onDropCompleted(View target, boolean success) {
     }
 }
+
diff --git a/src/com/android/launcher2/WidgetGalleryAdapter.java b/src/com/android/launcher2/WidgetListAdapter.java
similarity index 81%
rename from src/com/android/launcher2/WidgetGalleryAdapter.java
rename to src/com/android/launcher2/WidgetListAdapter.java
index bdb3551..5a569ea 100644
--- a/src/com/android/launcher2/WidgetGalleryAdapter.java
+++ b/src/com/android/launcher2/WidgetListAdapter.java
@@ -29,16 +29,18 @@
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import java.util.List;
 
-public class WidgetGalleryAdapter extends BaseAdapter {
+public class WidgetListAdapter extends BaseAdapter {
     private LayoutInflater mLayoutInflater;
     private PackageManager mPackageManager;
     private List<AppWidgetProviderInfo> mWidgets;
     private static final String TAG = "Launcher.WidgetGalleryAdapter";
 
-    WidgetGalleryAdapter(Context context) {
+    WidgetListAdapter(Context context) {
         mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
         mWidgets = widgetManager.getInstalledProviders();
@@ -58,12 +60,13 @@
     }
 
     public View getView(int position, View convertView, ViewGroup parent) {
-        ImageView imageView;
+        TextView textView;
 
         if (convertView == null) {
-            imageView = (ImageView) mLayoutInflater.inflate(R.layout.widget_item, parent, false);
+            textView = (TextView) mLayoutInflater.inflate(
+                    R.layout.home_customization_drawer_item, parent, false);
         } else {
-            imageView = (ImageView) convertView;
+            textView = (TextView) convertView;
         }
 
         AppWidgetProviderInfo info = mWidgets.get(position);
@@ -79,8 +82,10 @@
         if (image == null) {
             image = mPackageManager.getDrawable(info.provider.getPackageName(), info.icon, null);
         }
-        imageView.setImageDrawable(image);
+        image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
+        textView.setCompoundDrawables(null, image, null, null);
+        textView.setText(info.label);
 
-        return imageView;
+        return textView;
     }
 }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 0f41cc9..57195ad 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -48,6 +48,7 @@
 import android.view.animation.Animation.AnimationListener;
 import android.widget.Scroller;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -97,6 +98,7 @@
 
     private int mTouchState = TOUCH_STATE_REST;
 
+    private OnTouchListener mInterceptTouchListener;
     private OnLongClickListener mLongClickListener;
 
     private Launcher mLauncher;
@@ -512,6 +514,10 @@
         }
     }
 
+    public void setOnInterceptTouchListener(View.OnTouchListener listener) {
+        mInterceptTouchListener = listener;
+    }
+
     /**
      * Registers the specified listener on each screen contained in this workspace.
      *
@@ -747,6 +753,9 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)) {
+            return true;
+        }
         final boolean workspaceLocked = mLauncher.isWorkspaceLocked();
         final boolean allAppsVisible = mLauncher.isAllAppsVisible();
         if (workspaceLocked || allAppsVisible) {
@@ -1289,7 +1298,12 @@
             mVacantCache = layout.findAllVacantCells(null, ignoreView);
         }
 
-        return mVacantCache.findCellForSpan(mTempEstimate, spanX, spanY, false);
+        if (mVacantCache.findCellForSpan(mTempEstimate, spanX, spanY, false)) {
+            return true;
+        } else {
+            Toast.makeText(getContext(), getContext().getString(R.string.out_of_space), Toast.LENGTH_SHORT).show();
+            return false;
+        }
     }
 
     /**