Initial changes to add Applications tab in the customization drawer for usability testing.

- Also adding padding attributes for the dynamic layouts created for each page.

Change-Id: I76a7b6b8f4d83329c506fd6055f910575d0c200f
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index a2a3793..04e1cd9 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -68,6 +68,10 @@
 
     private int mCellCountX;
     private int mCellCountY;
+    private int mPageLayoutPaddingTop;
+    private int mPageLayoutPaddingBottom;
+    private int mPageLayoutPaddingLeft;
+    private int mPageLayoutPaddingRight;
 
     private final LayoutInflater mInflater;
 
@@ -90,6 +94,14 @@
         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0);
         mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6);
         mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
+        mPageLayoutPaddingTop = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingTop, 10);
+        mPageLayoutPaddingBottom = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingBottom, 10);
+        mPageLayoutPaddingLeft = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingLeft, 10);
+        mPageLayoutPaddingRight = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingRight, 10);
         mInflater = LayoutInflater.from(context);
         a.recycle();
         setSoundEffectsEnabled(false);
@@ -354,6 +366,8 @@
         for (int i = curNumPages; i < numPages; ++i) {
             PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
             layout.setCellCount(mCellCountX, mCellCountY);
+            layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop,
+                    mPageLayoutPaddingRight, mPageLayoutPaddingBottom);
             addView(layout);
         }
 
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 8fb3025..ead258c 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -59,7 +59,8 @@
         WidgetCustomization,
         FolderCustomization,
         ShortcutCustomization,
-        WallpaperCustomization
+        WallpaperCustomization,
+        ApplicationCustomization
     }
 
     /**
@@ -109,9 +110,14 @@
     private List<ResolveInfo> mFolderList;
     private List<ResolveInfo> mShortcutList;
     private List<ResolveInfo> mWallpaperList;
+    private List<ApplicationInfo> mApps;
 
-    private static final int sCellCountX = 8;
-    private static final int sCellCountY = 4;
+    private int mCellCountX;
+    private int mCellCountY;
+    private int mPageLayoutPaddingTop;
+    private int mPageLayoutPaddingBottom;
+    private int mPageLayoutPaddingLeft;
+    private int mPageLayoutPaddingRight;
     private static final int sMinWidgetCellHSpan = 2;
     private static final int sMaxWidgetCellHSpan = 4;
 
@@ -132,14 +138,27 @@
     public CustomizePagedView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomizePagedView,
+        TypedArray a;
+        a = context.obtainStyledAttributes(attrs, R.styleable.CustomizePagedView,
                 defStyle, 0);
+        mMaxWidgetsCellHSpan = a.getInt(R.styleable.CustomizePagedView_widgetCellCountX, 8);
+        a.recycle();
+        a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0);
+        mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 7);
+        mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4);
+        mPageLayoutPaddingTop = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingTop, 10);
+        mPageLayoutPaddingBottom = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingBottom, 10);
+        mPageLayoutPaddingLeft = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingLeft, 10);
+        mPageLayoutPaddingRight = a.getDimensionPixelSize(
+                R.styleable.PagedView_pageLayoutPaddingRight, 10);
+        a.recycle();
         mCustomizationType = CustomizationType.WidgetCustomization;
         mWidgetPages = new ArrayList<ArrayList<AppWidgetProviderInfo>>();
         mWorkspaceWidgetLayout = new PagedViewCellLayout(context);
         mInflater = LayoutInflater.from(context);
-        mMaxWidgetsCellHSpan = a.getInt(R.styleable.CustomizePagedView_widgetCellCountX, 8);
-        a.recycle();
 
         setVisibility(View.GONE);
         setSoundEffectsEnabled(false);
@@ -152,6 +171,93 @@
         mPackageManager = context.getPackageManager();
     }
 
+    /**
+     * Sets the list of applications that launcher has loaded.
+     */
+    public void setApps(ArrayList<ApplicationInfo> list) {
+        mApps = list;
+        Collections.sort(mApps, LauncherModel.APP_NAME_COMPARATOR);
+        mPageViewIconCache.clear();
+        invalidatePageData();
+    }
+
+    /**
+     * Convenience function to add new items to the set of applications that were previously loaded.
+     * Called by both updateApps() and setApps().
+     */
+    private void addAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+        // we add it in place, in alphabetical order
+        final int count = list.size();
+        for (int i = 0; i < count; ++i) {
+            final ApplicationInfo info = list.get(i);
+            final int index = Collections.binarySearch(mApps, info, LauncherModel.APP_NAME_COMPARATOR);
+            if (index < 0) {
+                mApps.add(-(index + 1), info);
+            }
+        }
+    }
+
+    /**
+     * Adds new applications to the loaded list, and notifies the paged view to update itself.
+     */
+    public void addApps(ArrayList<ApplicationInfo> list) {
+        addAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+
+    /**
+     * Convenience function to remove items to the set of applications that were previously loaded.
+     * Called by both updateApps() and removeApps().
+     */
+    private void removeAppsWithoutInvalidate(ArrayList<ApplicationInfo> list) {
+        // loop through all the apps and remove apps that have the same component
+        final int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            final ApplicationInfo info = list.get(i);
+            int removeIndex = findAppByComponent(mApps, info);
+            if (removeIndex > -1) {
+                mApps.remove(removeIndex);
+                mPageViewIconCache.removeOutline(info);
+            }
+        }
+    }
+
+    /**
+     * Removes applications from the loaded list, and notifies the paged view to update itself.
+     */
+    public void removeApps(ArrayList<ApplicationInfo> list) {
+        removeAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+
+    /**
+     * Updates a set of applications from the loaded list, and notifies the paged view to update
+     * itself.
+     */
+    public void updateApps(ArrayList<ApplicationInfo> list) {
+        // We remove and re-add the updated applications list because it's properties may have
+        // changed (ie. the title), and this will ensure that the items will be in their proper
+        // place in the list.
+        removeAppsWithoutInvalidate(list);
+        addAppsWithoutInvalidate(list);
+        invalidatePageData();
+    }
+
+    /**
+     * Convenience function to find matching ApplicationInfos for removal.
+     */
+    private int findAppByComponent(List<ApplicationInfo> list, ApplicationInfo item) {
+        ComponentName removeComponent = item.intent.getComponent();
+        final int length = list.size();
+        for (int i = 0; i < length; ++i) {
+            ApplicationInfo info = list.get(i);
+            if (info.intent.getComponent().equals(removeComponent)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
     public void update() {
         Context context = getContext();
 
@@ -312,6 +418,13 @@
                 }
             });
             return true;
+        case ApplicationCustomization:
+            // Pick up the application for dropping
+            ApplicationInfo app = (ApplicationInfo) v.getTag();
+            app = new ApplicationInfo(app);
+
+            mDragController.startDrag(v, this, app, DragController.DRAG_ACTION_COPY);
+            return true;
         }
         return false;
     }
@@ -417,12 +530,13 @@
     }
 
     private void setupPage(PagedViewCellLayout layout) {
-        layout.setCellCount(sCellCountX, sCellCountY);
-        layout.setPadding(20, 10, 20, 0);
+        layout.setCellCount(mCellCountX, mCellCountY);
+        layout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop, mPageLayoutPaddingRight,
+                mPageLayoutPaddingBottom);
     }
 
     private void setupWorkspaceLayout() {
-        mWorkspaceWidgetLayout.setCellCount(sCellCountX, sCellCountY);
+        mWorkspaceWidgetLayout.setCellCount(mCellCountX, mCellCountY);
         mWorkspaceWidgetLayout.setPadding(20, 10, 20, 0);
 
         mMaxWidgetWidth = mWorkspaceWidgetLayout.estimateCellWidth(sMaxWidgetCellHSpan);
@@ -486,7 +600,7 @@
         removeAllViews();
 
         // ensure that we have the right number of pages
-        int numPages = (int) Math.ceil((float) list.size() / (sCellCountX * sCellCountY));
+        int numPages = (int) Math.ceil((float) list.size() / (mCellCountX * mCellCountY));
         for (int i = 0; i < numPages; ++i) {
             PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
             setupPage(layout);
@@ -496,7 +610,7 @@
 
     private void syncListPageItems(int page, List<ResolveInfo> list) {
         // ensure that we have the right number of items on the pages
-        int numCells = sCellCountX * sCellCountY;
+        int numCells = mCellCountX * mCellCountY;
         int startIndex = page * numCells;
         int endIndex = Math.min(startIndex + numCells, list.size());
         PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page);
@@ -514,8 +628,48 @@
             }
 
             final int index = i - startIndex;
-            final int x = index % sCellCountX;
-            final int y = index / sCellCountX;
+            final int x = index % mCellCountX;
+            final int y = index / mCellCountX;
+            setupPage(layout);
+            layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
+        }
+    }
+
+    private void syncAppPages() {
+        if (mApps == null) return;
+
+        // We need to repopulate with PagedViewCellLayouts
+        removeAllViews();
+
+        // Ensure that we have the right number of pages
+        int numPages = (int) Math.ceil((float) mApps.size() / (mCellCountX * mCellCountY));
+        for (int i = 0; i < numPages; ++i) {
+            PagedViewCellLayout layout = new PagedViewCellLayout(getContext());
+            setupPage(layout);
+            addView(layout);
+        }
+    }
+
+    private void syncAppPageItems(int page) {
+        if (mApps == null) return;
+
+        // ensure that we have the right number of items on the pages
+        int numCells = mCellCountX * mCellCountY;
+        int startIndex = page * numCells;
+        int endIndex = Math.min(startIndex + numCells, mApps.size());
+        PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(page);
+        // TODO: we can optimize by just re-applying to existing views
+        layout.removeAllViews();
+        for (int i = startIndex; i < endIndex; ++i) {
+            final ApplicationInfo info = mApps.get(i);
+            PagedViewIcon icon = (PagedViewIcon) mInflater.inflate(
+                    R.layout.all_apps_paged_view_application, layout, false);
+            icon.applyFromApplicationInfo(info, mPageViewIconCache);
+            icon.setOnLongClickListener(this);
+
+            final int index = i - startIndex;
+            final int x = index % mCellCountX;
+            final int y = index / mCellCountX;
             setupPage(layout);
             layout.addViewToCellLayout(icon, -1, i, new PagedViewCellLayout.LayoutParams(x,y, 1,1));
         }
@@ -540,6 +694,10 @@
             syncListPages(mWallpaperList);
             centerPagedViewCellLayouts = true;
             break;
+        case ApplicationCustomization:
+            syncAppPages();
+            centerPagedViewCellLayouts = false;
+            break;
         default:
             removeAllViews();
             setCurrentPage(0);
@@ -579,6 +737,9 @@
         case WallpaperCustomization:
             syncListPageItems(page, mWallpaperList);
             break;
+        case ApplicationCustomization:
+            syncAppPageItems(page);
+            break;
         }
     }
 
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index d619aa2..c82f998 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -177,6 +177,7 @@
 
     // tags for the customization tabs
     private static final String WIDGETS_TAG = "widgets";
+    private static final String APPLICATIONS_TAG = "applications";
     private static final String FOLDERS_TAG = "folders";
     private static final String SHORTCUTS_TAG = "shortcuts";
     private static final String WALLPAPERS_TAG = "wallpapers";
@@ -292,15 +293,18 @@
             String widgetsLabel = getString(R.string.widgets_tab_label);
             mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(WIDGETS_TAG)
                     .setIndicator(widgetsLabel).setContent(contentFactory));
+            String applicationsLabel = getString(R.string.applications_tab_label);
+            mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(APPLICATIONS_TAG)
+                    .setIndicator(applicationsLabel).setContent(contentFactory));
             String foldersLabel = getString(R.string.folders_tab_label);
             mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(FOLDERS_TAG)
                     .setIndicator(foldersLabel).setContent(contentFactory));
-            String shortcutsLabel = getString(R.string.shortcuts_tab_label);
-            mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(SHORTCUTS_TAG)
-                    .setIndicator(shortcutsLabel).setContent(contentFactory));
             String wallpapersLabel = getString(R.string.wallpapers_tab_label);
             mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(WALLPAPERS_TAG)
                     .setIndicator(wallpapersLabel).setContent(contentFactory));
+            String shortcutsLabel = getString(R.string.shortcuts_tab_label);
+            mHomeCustomizationDrawer.addTab(mHomeCustomizationDrawer.newTabSpec(SHORTCUTS_TAG)
+                    .setIndicator(shortcutsLabel).setContent(contentFactory));
 
             // TEMP: just styling the tab widget to be a bit nicer until we get the actual
             // new assets
@@ -327,20 +331,23 @@
                             if (tag == WIDGETS_TAG) {
                                 mCustomizePagedView.setCustomizationFilter(
                                     CustomizePagedView.CustomizationType.WidgetCustomization);
+                            } else if (tag == APPLICATIONS_TAG) {
+                                mCustomizePagedView.setCustomizationFilter(
+                                        CustomizePagedView.CustomizationType.ApplicationCustomization);
                             } else if (tag == FOLDERS_TAG) {
                                 mCustomizePagedView.setCustomizationFilter(
                                     CustomizePagedView.CustomizationType.FolderCustomization);
-                            } else if (tag == SHORTCUTS_TAG) {
-                                mCustomizePagedView.setCustomizationFilter(
-                                    CustomizePagedView.CustomizationType.ShortcutCustomization);
                             } else if (tag == WALLPAPERS_TAG) {
                                 mCustomizePagedView.setCustomizationFilter(
                                     CustomizePagedView.CustomizationType.WallpaperCustomization);
+                            } else if (tag == SHORTCUTS_TAG) {
+                                mCustomizePagedView.setCustomizationFilter(
+                                        CustomizePagedView.CustomizationType.ShortcutCustomization);
                             }
 
                             final float alpha = mCustomizePagedView.getAlpha();
-                            ValueAnimator alphaAnim = new ObjectAnimator(duration, mCustomizePagedView,
-                                    "alpha", alpha, 1.0f);
+                            ValueAnimator alphaAnim = new ObjectAnimator(duration,
+                                    mCustomizePagedView, "alpha", alpha, 1.0f);
                             alphaAnim.start();
                         }
                     });
@@ -2976,6 +2983,7 @@
      */
     public void bindAllApplications(ArrayList<ApplicationInfo> apps) {
         mAllAppsGrid.setApps(apps);
+        mCustomizePagedView.setApps(apps);
         updateAppMarketIcon();
     }
 
@@ -2987,6 +2995,7 @@
     public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {
         removeDialog(DIALOG_CREATE_SHORTCUT);
         mAllAppsGrid.addApps(apps);
+        mCustomizePagedView.addApps(apps);
         updateAppMarketIcon();
     }
 
@@ -2999,6 +3008,7 @@
         removeDialog(DIALOG_CREATE_SHORTCUT);
         mWorkspace.updateShortcuts(apps);
         mAllAppsGrid.updateApps(apps);
+        mCustomizePagedView.updateApps(apps);
         updateAppMarketIcon();
     }
 
@@ -3013,6 +3023,7 @@
             mWorkspace.removeItems(apps);
         }
         mAllAppsGrid.removeApps(apps);
+        mCustomizePagedView.removeApps(apps);
         updateAppMarketIcon();
     }