Adding menu to jump to shortcuts page in widgets tab

- Fixing bug in PagedView when setting the current page
- Fixing small visual issue with flashing scroll indicator
- Fixing slightly offset holographic icons

Change-Id: Ic6ce6365daca41cb5a73706c7c4b078f33a4e39c
diff --git a/src/com/android/launcher2/AddAdapter.java b/src/com/android/launcher2/AddAdapter.java
index d1076b1..5b7e92c 100644
--- a/src/com/android/launcher2/AddAdapter.java
+++ b/src/com/android/launcher2/AddAdapter.java
@@ -35,14 +35,14 @@
 public class AddAdapter extends BaseAdapter {
 
     private final LayoutInflater mInflater;
-    
+
     private final ArrayList<ListItem> mItems = new ArrayList<ListItem>();
-    
+
     public static final int ITEM_SHORTCUT = 0;
     public static final int ITEM_APPWIDGET = 1;
     public static final int ITEM_APPLICATION = 2;
     public static final int ITEM_WALLPAPER = 3;
-    
+
     /**
      * Specific item in our list.
      */
@@ -50,7 +50,7 @@
         public final CharSequence text;
         public final Drawable image;
         public final int actionTag;
-        
+
         public ListItem(Resources res, int textResourceId, int imageResourceId, int actionTag) {
             text = res.getString(textResourceId);
             if (imageResourceId != -1) {
@@ -66,16 +66,17 @@
         super();
 
         mInflater = (LayoutInflater) launcher.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        
+
         // Create default actions
         Resources res = launcher.getResources();
-        
+
         mItems.add(new ListItem(res, R.string.group_applications,
                 R.drawable.ic_launcher_application, ITEM_APPLICATION));
 
         mItems.add(new ListItem(res, R.string.group_widgets,
                 R.drawable.ic_launcher_appwidget, ITEM_APPWIDGET));
-        
+        mItems.add(new ListItem(res, R.string.group_shortcuts,
+                R.drawable.ic_launcher_application, ITEM_SHORTCUT));
         mItems.add(new ListItem(res, R.string.group_wallpapers,
                 R.drawable.ic_launcher_wallpaper, ITEM_WALLPAPER));
 
@@ -83,16 +84,16 @@
 
     public View getView(int position, View convertView, ViewGroup parent) {
         ListItem item = (ListItem) getItem(position);
-        
+
         if (convertView == null) {
             convertView = mInflater.inflate(R.layout.add_list_item, parent, false);
         }
-        
+
         TextView textView = (TextView) convertView;
         textView.setTag(item);
         textView.setText(item.text);
         textView.setCompoundDrawablesWithIntrinsicBounds(item.image, null, null, null);
-        
+
         return convertView;
     }
 
@@ -107,5 +108,4 @@
     public long getItemId(int position) {
         return position;
     }
-    
 }
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 714e7f9..d07b321 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -181,6 +181,7 @@
     private int mWidgetWidthGap, mWidgetHeightGap;
     private int mShortcutCountX, mShortcutCountY;
     private int mShortcutWidthGap, mShortcutHeightGap;
+    private int mNumWidgetPages, mNumShortcutPages;
     private final int mWidgetPreviewIconPaddedDimension;
     private final float sWidgetPreviewIconPaddingPercentage = 0.25f;
     private PagedViewCellLayout mWidgetSpacingLayout;
@@ -287,12 +288,16 @@
         mShortcutCountX = Math.max(1, (int) Math.round(mCellCountX / 2f));
         mShortcutCountY = Math.max(1, (int) Math.round(mCellCountY / 2f));
 
+        mNumWidgetPages = (int) Math.ceil(mWidgets.size() /
+                (float) (mWidgetCountX * mWidgetCountY));
+        mNumShortcutPages = (int) Math.ceil(mShortcuts.size() /
+                (float) (mShortcutCountX * mShortcutCountY));
+
         // Force a measure to update recalculate the gaps
         int widthSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.AT_MOST);
         int heightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST);
         mWidgetSpacingLayout.measure(widthSpec, heightSpec);
         mContentWidth = mWidgetSpacingLayout.getContentWidth();
-
         invalidatePageData();
     }
 
@@ -495,14 +500,20 @@
 
     public void setContentType(ContentType type) {
         mContentType = type;
-        setCurrentPage(0);
-        invalidatePageData();
+        invalidatePageData(0);
     }
 
     public boolean isContentType(ContentType type) {
         return (mContentType == type);
     }
 
+    public void setCurrentPageToWidgets() {
+        invalidatePageData(0);
+    }
+    public void setCurrentPageToShortcuts() {
+        invalidatePageData(mNumWidgetPages);
+    }
+
     /*
      * Apps PagedView implementation
      */
@@ -848,14 +859,10 @@
         Context context = getContext();
         int[] countX = { mWidgetCountX, mShortcutCountX };
         int[] countY = { mWidgetCountY, mShortcutCountY };
-        Object[] collection = { mWidgets, mShortcuts };
+        int[] numPages = { mNumWidgetPages, mNumShortcutPages };
         for (int i = 0; i < 2; ++i) {
-            ArrayList<Object> list = (ArrayList<Object>) collection[i];
-            int numItemsPerPage = countX[i] * countY[i];
-            int numItemPages = (int) Math.ceil(list.size() / (float) numItemsPerPage);
-            for (int j = 0; j < numItemPages; ++j) {
-                PagedViewGridLayout layout = new PagedViewGridLayout(context, countX[i],
-                        countY[i]);
+            for (int j = 0; j < numPages[i]; ++j) {
+                PagedViewGridLayout layout = new PagedViewGridLayout(context, countX[i], countY[i]);
                 setupPage(layout);
                 addView(layout);
             }
@@ -1130,10 +1137,9 @@
             // Reset to the first page of the Apps pane
             AppsCustomizeTabHost tabs = (AppsCustomizeTabHost)
                     mLauncher.findViewById(R.id.apps_customize_pane);
-            tabs.setCurrentTabByTag(tabs.getTabTagForContentType(ContentType.Applications));
+            tabs.selectAppsTab();
         } else if (getCurrentPage() != 0) {
-            setCurrentPage(0);
-            invalidatePageData();
+            invalidatePageData(0);
         }
     }
     @Override
diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java
index d3215f0..c2d1341 100644
--- a/src/com/android/launcher2/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher2/AppsCustomizeTabHost.java
@@ -52,12 +52,29 @@
     }
 
     /**
-     * Convenience methods to select specific tabs
+     * Convenience methods to select specific tabs.  We want to set the content type immediately
+     * in these cases, but we note that we still call setCurrentTabByTag() so that the tab view
+     * reflects the new content (but doesn't do the animation and logic associated with changing
+     * tabs manually).
      */
+    private void setContentTypeImmediate(AppsCustomizePagedView.ContentType type) {
+        onTabChangedStart();
+        onTabChangedEnd(type);
+    }
     void selectAppsTab() {
+        setContentTypeImmediate(AppsCustomizePagedView.ContentType.Applications);
         setCurrentTabByTag(APPS_TAB_TAG);
     }
     void selectWidgetsTab() {
+        setContentTypeImmediate(AppsCustomizePagedView.ContentType.Widgets);
+        mAppsCustomizePane.setCurrentPageToWidgets();
+
+        setCurrentTabByTag(WIDGETS_TAB_TAG);
+    }
+    void selectShortcutsTab() {
+        setContentTypeImmediate(AppsCustomizePagedView.ContentType.Widgets);
+        mAppsCustomizePane.setCurrentPageToShortcuts();
+
         setCurrentTabByTag(WIDGETS_TAB_TAG);
     }
 
@@ -135,6 +152,13 @@
         return super.onTouchEvent(event);
     }
 
+    private void onTabChangedStart() {
+        mAppsCustomizePane.hideScrollingIndicator(false);
+    }
+    private void onTabChangedEnd(AppsCustomizePagedView.ContentType type) {
+        mAppsCustomizePane.setContentType(type);
+    }
+
     @Override
     public void onTabChanged(String tabId) {
         final AppsCustomizePagedView.ContentType type = getContentTypeForTabTag(tabId);
@@ -148,11 +172,11 @@
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationStart(android.animation.Animator animation) {
-                    mAppsCustomizePane.hideScrollingIndicator(false);
+                    onTabChangedStart();
                 }
                 @Override
                 public void onAnimationEnd(android.animation.Animator animation) {
-                    mAppsCustomizePane.setContentType(type);
+                    onTabChangedEnd(type);
 
                     ObjectAnimator anim = ObjectAnimator.ofFloat(mAppsCustomizePane, "alpha", 1f);
                     anim.setDuration(duration);
@@ -206,7 +230,7 @@
 
     /* LauncherTransitionable overrides */
     @Override
-    public void onLauncherTransitionStart(Animator animation) {
+    public void onLauncherTransitionStart(Animator animation, boolean toWorkspace) {
         // isHardwareAccelerated() checks if we're attached to a window and if that
         // window is HW accelerated-- we were sometimes not attached to a window
         // and buildLayer was throwing an IllegalStateException
@@ -221,11 +245,13 @@
     }
 
     @Override
-    public void onLauncherTransitionEnd(Animator animation) {
+    public void onLauncherTransitionEnd(Animator animation, boolean toWorkspace) {
         if (animation != null) {
             setLayerType(LAYER_TYPE_NONE, null);
         }
 
-        mAppsCustomizePane.flashScrollingIndicator();
+        if (!toWorkspace) {
+            mAppsCustomizePane.flashScrollingIndicator();
+        }
     }
 }
diff --git a/src/com/android/launcher2/HolographicPagedViewIcon.java b/src/com/android/launcher2/HolographicPagedViewIcon.java
index 7123e2a..dda233e 100644
--- a/src/com/android/launcher2/HolographicPagedViewIcon.java
+++ b/src/com/android/launcher2/HolographicPagedViewIcon.java
@@ -48,7 +48,7 @@
             int hspace = getWidth() - compoundPaddingRight - compoundPaddingLeft;
             canvas.drawBitmap(overlay,
                     offset + compoundPaddingLeft + (hspace - overlay.getWidth()) / 2,
-                    mPaddingTop,
+                    mOriginalIcon.getPaddingTop(),
                     mPaint);
         }
     }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index ae301c6..795d5cc 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -2088,7 +2088,7 @@
             alphaAnim.start();
 
             if (toView instanceof LauncherTransitionable) {
-                ((LauncherTransitionable) toView).onLauncherTransitionStart(scaleAnim);
+                ((LauncherTransitionable) toView).onLauncherTransitionStart(scaleAnim, false);
             }
             scaleAnim.addListener(new AnimatorListenerAdapter() {
                 @Override
@@ -2107,7 +2107,7 @@
                     toView.setScaleX(1.0f);
                     toView.setScaleY(1.0f);
                     if (toView instanceof LauncherTransitionable) {
-                        ((LauncherTransitionable) toView).onLauncherTransitionEnd(scaleAnim);
+                        ((LauncherTransitionable) toView).onLauncherTransitionEnd(scaleAnim, false);
                     }
 
                     if (!springLoaded && !LauncherApplication.isScreenLarge()) {
@@ -2132,8 +2132,8 @@
             toView.setVisibility(View.VISIBLE);
             toView.bringToFront();
             if (toView instanceof LauncherTransitionable) {
-                ((LauncherTransitionable) toView).onLauncherTransitionStart(null);
-                ((LauncherTransitionable) toView).onLauncherTransitionEnd(null);
+                ((LauncherTransitionable) toView).onLauncherTransitionStart(null, false);
+                ((LauncherTransitionable) toView).onLauncherTransitionEnd(null, false);
 
                 if (!springLoaded && !LauncherApplication.isScreenLarge()) {
                     // Hide the workspace scrollbar
@@ -2188,22 +2188,16 @@
                 }
             });
             if (fromView instanceof LauncherTransitionable) {
-                ((LauncherTransitionable) fromView).onLauncherTransitionStart(alphaAnim);
+                ((LauncherTransitionable) fromView).onLauncherTransitionStart(alphaAnim, true);
             }
             alphaAnim.addListener(new AnimatorListenerAdapter() {
                 @Override
-                public void onAnimationStart(android.animation.Animator animation) {
-                    if (!springLoaded && !LauncherApplication.isScreenLarge()) {
-                        // Show the workspace scrollbar
-                        mWorkspace.flashScrollingIndicator();
-                    }
-                }
-                @Override
                 public void onAnimationEnd(Animator animation) {
                     fromView.setVisibility(View.GONE);
                     if (fromView instanceof LauncherTransitionable) {
-                        ((LauncherTransitionable) fromView).onLauncherTransitionEnd(alphaAnim);
+                        ((LauncherTransitionable) fromView).onLauncherTransitionEnd(alphaAnim,true);
                     }
+                    mWorkspace.flashScrollingIndicator();
                 }
             });
 
@@ -2212,8 +2206,8 @@
         } else {
             fromView.setVisibility(View.GONE);
             if (fromView instanceof LauncherTransitionable) {
-                ((LauncherTransitionable) fromView).onLauncherTransitionStart(null);
-                ((LauncherTransitionable) fromView).onLauncherTransitionEnd(null);
+                ((LauncherTransitionable) fromView).onLauncherTransitionStart(null, true);
+                ((LauncherTransitionable) fromView).onLauncherTransitionEnd(null, true);
 
                 if (!springLoaded && !LauncherApplication.isScreenLarge()) {
                     // Flash the workspace scrollbar
@@ -2565,7 +2559,6 @@
 
             final AlertDialog.Builder builder = new AlertDialog.Builder(Launcher.this, 
                     AlertDialog.THEME_HOLO_DARK);
-            builder.setTitle(getString(R.string.menu_item_add_item));
             builder.setAdapter(mAdapter, this);
 
             AlertDialog dialog = builder.create();
@@ -2604,7 +2597,7 @@
             switch (item.actionTag) {
                 case AddAdapter.ITEM_SHORTCUT: {
                     if (mAppsCustomizeTabHost != null) {
-                        mAppsCustomizeTabHost.selectWidgetsTab();
+                        mAppsCustomizeTabHost.selectShortcutsTab();
                     }
                     showAllApps(true);
                     break;
@@ -2991,6 +2984,6 @@
 }
 
 interface LauncherTransitionable {
-    void onLauncherTransitionStart(Animator animation);
-    void onLauncherTransitionEnd(Animator animation);
+    void onLauncherTransitionStart(Animator animation, boolean toWorkspace);
+    void onLauncherTransitionEnd(Animator animation, boolean toWorkspace);
 }
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index f8c956b..26f0e57 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -291,6 +291,7 @@
 
         mCurrentPage = Math.max(0, Math.min(currentPage, getPageCount() - 1));
         updateCurrentPageScroll();
+        updateScrollingIndicator();
         notifyPageSwitchListener();
         invalidate();
     }
@@ -1618,6 +1619,9 @@
     }
 
     protected void invalidatePageData() {
+        invalidatePageData(-1);
+    }
+    protected void invalidatePageData(int currentPage) {
         if (!mIsDataReady) {
             return;
         }
@@ -1626,6 +1630,16 @@
             // Update all the pages
             syncPages();
 
+            // We must force a measure after we've loaded the pages to update the content width and
+            // to determine the full scroll width
+            measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+
+            // Set a new page as the current page if necessary
+            if (currentPage > -1) {
+                setCurrentPage(currentPage);
+            }
+
             // Mark each of the pages as dirty
             final int count = getChildCount();
             mDirtyPageContent.clear();
@@ -1659,14 +1673,16 @@
         return !LauncherApplication.isScreenLarge();
     }
 
+    Runnable hideScrollingIndicatorRunnable = new Runnable() {
+        @Override
+        public void run() {
+            hideScrollingIndicator(false);
+        }
+    };
     protected void flashScrollingIndicator() {
+        removeCallbacks(hideScrollingIndicatorRunnable);
         showScrollingIndicator();
-        postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                hideScrollingIndicator(false);
-            }
-        }, sScrollIndicatorFlashDuration);
+        postDelayed(hideScrollingIndicatorRunnable, sScrollIndicatorFlashDuration);
     }
 
     protected void showScrollingIndicator() {