merge in ics-release history after reset to master
diff --git a/res/values-large/dimens.xml b/res/values-large/dimens.xml
index fa660e5..970a200 100644
--- a/res/values-large/dimens.xml
+++ b/res/values-large/dimens.xml
@@ -95,4 +95,10 @@
 
     <!-- Max number of rows in all apps, because too many looks weird. -->
     <integer name="all_apps_view_maxCellCountY">6</integer>
+
+    <!-- Padding applied to AppWidgets -->
+    <dimen name="app_widget_padding_left">12dp</dimen>
+    <dimen name="app_widget_padding_right">12dp</dimen>
+    <dimen name="app_widget_padding_top">4dp</dimen>
+    <dimen name="app_widget_padding_bottom">20dp</dimen>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 9d159f9..f51f8b1 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -78,4 +78,10 @@
     <!-- Width/height gap overrides for the workspace -->
     <dimen name="workspace_width_gap">-1dp</dimen>
     <dimen name="workspace_height_gap">-1dp</dimen>
+
+    <!-- Padding applied to AppWidgets -->
+    <dimen name="app_widget_padding_left">0dp</dimen>
+    <dimen name="app_widget_padding_right">0dp</dimen>
+    <dimen name="app_widget_padding_top">0dp</dimen>
+    <dimen name="app_widget_padding_bottom">0dp</dimen>
 </resources>
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index 64e6f98..94e6af4 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -72,6 +72,7 @@
 
     private int mLastMeasureWidth = -1;
     private int mLastMeasureHeight = -1;
+    private boolean mWaitingToInitPages = true;
 
     private int mMaxCellCountY;
 
@@ -119,13 +120,16 @@
             mCellCountY = determineCellCountY(height, layout);
             mLastMeasureWidth = width;
             mLastMeasureHeight = height;
+            removeAllViews();
+            invalidatePageData();
         }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        if (mFirstLayout) {
+        if (mWaitingToInitPages) {
+            mWaitingToInitPages = false;
             invalidatePageData();
 
             // invalidatePageData() is what causes the child pages to be created. We need the
@@ -567,12 +571,17 @@
     }
 
     @Override
-    public void syncPages() {
-        if (mCellCountX <= 0 || mCellCountY <= 0) {
+    protected void invalidatePageData() {
+        if (mWaitingToInitPages || mCellCountX <= 0 || mCellCountY <= 0) {
             // We don't know our size yet, which means we haven't calculated cell count x/y;
             // onMeasure will call us once we figure out our size
             return;
         }
+        super.invalidatePageData();
+    }
+
+    @Override
+    public void syncPages() {
         // ensure that we have the right number of pages (min of 1, since we have placeholders)
         int numPages = Math.max(1,
                 (int) Math.ceil((float) mFilteredApps.size() / (mCellCountX * mCellCountY)));
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 5ac261f..e1256d0 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -151,6 +151,8 @@
 
     private AllAppsPagedView mAllAppsPagedView;
 
+    private boolean mWaitingToInitPages = true;
+
     public CustomizePagedView(Context context) {
         this(context, null, 0);
     }
@@ -208,6 +210,8 @@
             mPageContentWidth = layout.getContentWidth();
             mPageContentHeight = layout.getContentHeight();
             mMinPageWidth = layout.getWidthBeforeFirstLayout();
+            removeAllViews();
+            invalidatePageData();
         }
         if (mPageContentHeight > 0) {
             // Lock our height to the size of the page content
@@ -220,7 +224,8 @@
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        if (mFirstLayout) {
+        if (mWaitingToInitPages) {
+            mWaitingToInitPages = false;
             invalidatePageData();
 
             // invalidatePageData() is what causes the child pages to be created. We need the
@@ -1138,12 +1143,17 @@
     }
 
     @Override
-    public void syncPages() {
-        if (mFirstMeasure) {
+    protected void invalidatePageData() {
+        if (mWaitingToInitPages || mCellCountX <= 0 || mCellCountY <= 0) {
             // We don't know our size yet, which means we haven't calculated cell count x/y;
             // onMeasure will call us once we figure out our size
             return;
         }
+        super.invalidatePageData();
+    }
+
+    @Override
+    public void syncPages() {
         boolean enforceMinimumPagedWidths = false;
         boolean centerPagedViewCellLayouts = false;
         switch (mCustomizationType) {
diff --git a/src/com/android/launcher2/FastBitmapDrawable.java b/src/com/android/launcher2/FastBitmapDrawable.java
index a453294..3e75fb6 100644
--- a/src/com/android/launcher2/FastBitmapDrawable.java
+++ b/src/com/android/launcher2/FastBitmapDrawable.java
@@ -49,6 +49,11 @@
     }
 
     @Override
+    public void setColorFilter(ColorFilter cf) {
+        mPaint.setColorFilter(cf);
+    }
+
+    @Override
     public int getOpacity() {
         return PixelFormat.TRANSLUCENT;
     }
@@ -64,10 +69,6 @@
     }
 
     @Override
-    public void setColorFilter(ColorFilter cf) {
-    }
-
-    @Override
     public int getIntrinsicWidth() {
         return mWidth;
     }
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 76e9b35..0b35acb 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -26,6 +26,7 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -81,6 +82,7 @@
     private int mMaxCountY;
     private Rect mNewSize = new Rect();
     private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
+    private Drawable mIconDrawable;
     boolean mItemsInvalidated = false;
 
     /**
@@ -144,6 +146,7 @@
             mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
             mDragItemPosition[0] = item.cellX;
             mDragItemPosition[1] = item.cellY;
+            mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
             mInfo.remove(item);
 
             mDragItem = item;
@@ -154,6 +157,10 @@
         return true;
     }
 
+    public Drawable getDragDrawable() {
+        return mIconDrawable;
+    }
+
     /**
      * We need to handle touch events to prevent them from falling through to the workspace below.
      */
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index 0091a28..e97676d 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -26,6 +26,7 @@
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
@@ -45,14 +46,32 @@
     Folder mFolder;
     FolderInfo mInfo;
 
+    // The number of icons to display in the
     private static final int NUM_ITEMS_IN_PREVIEW = 4;
-    private static final float ICON_ANGLE = 15f;
     private static final int CONSUMPTION_ANIMATION_DURATION = 100;
+
+    // The degree to which the inner ring grows when accepting drop
     private static final float INNER_RING_GROWTH_FACTOR = 0.1f;
-    private static final float OUTER_RING_BASELINE_SCALE = 0.7f;
-    private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
+
+    // The degree to which the inner ring is scaled in its natural state
     private static final float INNER_RING_BASELINE_SCALE = 1.0f;
 
+    // The degree to which the outer ring grows when accepting drop
+    private static final float OUTER_RING_BASELINE_SCALE = 0.7f;
+
+    // The degree to which the outer ring is scaled in its natural state
+    private static final float OUTER_RING_GROWTH_FACTOR = 0.3f;
+
+    // The amount of vertical spread between items in the stack [0...1]
+    private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f;
+
+    // The degree to which the item in the back of the stack is scaled [0...1]
+    // (0 means it's not scaled at all, 1 means it's scaled to nothing)
+    private static final float PERSPECTIVE_SCALE_FACTOR = 0.3f;
+
+    // The percentage of the FolderIcons view that will be dedicated to the items preview
+    private static final float SPACE_PERCENTAGE_FOR_ICONS = 0.8f;
+
     public static Drawable sFolderOuterRingDrawable = null;
     public static Drawable sFolderInnerRingDrawable = null;
 
@@ -148,8 +167,6 @@
     }
 
     private void animateToAcceptState() {
-        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams();
-
         ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
         va.setDuration(CONSUMPTION_ANIMATION_DURATION);
         va.addUpdateListener(new AnimatorUpdateListener() {
@@ -253,24 +270,46 @@
             mOriginalHeight = getMeasuredHeight();
         }
 
-        int xShift = (mOriginalWidth - d.getIntrinsicWidth()) / 2;
-        int yShift = (mOriginalHeight - d.getIntrinsicHeight()) / 2;
-        canvas.translate(xShift, yShift);
+        int unscaledHeight = (int) (d.getIntrinsicHeight() * (1 + PERSPECTIVE_SHIFT_FACTOR));
+        float baselineIconScale = SPACE_PERCENTAGE_FOR_ICONS / (unscaledHeight / (mOriginalHeight * 1.0f));
+
+        int baselineHeight = (int) (d.getIntrinsicHeight() * baselineIconScale);
+        int totalStackHeight = (int) (baselineHeight * (1 + PERSPECTIVE_SHIFT_FACTOR));
+        int baselineWidth = (int) (d.getIntrinsicWidth() * baselineIconScale);
+        float maxPerpectiveShift = baselineHeight * PERSPECTIVE_SHIFT_FACTOR;
 
         ArrayList<View> items = mFolder.getItemsInReadingOrder();
         int firstItemIndex = Math.max(0, items.size() - NUM_ITEMS_IN_PREVIEW);
+
+        int xShift = (int) (mOriginalWidth - baselineWidth) / 2;
+        int yShift = (int) (mOriginalHeight - totalStackHeight) / 2;
+        canvas.translate(xShift, yShift);
         for (int i = firstItemIndex; i < items.size(); i++) {
+            int index = i - firstItemIndex;
+            index += Math.max(0, NUM_ITEMS_IN_PREVIEW - items.size());
+
+            float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1);
+            float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r));
+            r = (float) Math.pow(r, 2);
+
+            float transY = r * maxPerpectiveShift;
+            float transX = (1 - scale) * baselineWidth / 2.0f;
+
             v = (TextView) items.get(i);
             d = v.getCompoundDrawables()[1];
 
-            canvas.translate(d.getIntrinsicWidth() / 2, d.getIntrinsicHeight() / 2);
-            canvas.rotate(i == firstItemIndex ? ICON_ANGLE : -ICON_ANGLE);
-            canvas.translate(-d.getIntrinsicWidth() / 2, -d.getIntrinsicHeight() / 2);
+            canvas.save();
+            canvas.translate(transX, transY);
+            canvas.scale(baselineIconScale * scale, baselineIconScale * scale);
 
+            int overlayAlpha = (int) (80 * (1 - r));
             if (d != null) {
                 d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
+                d.setColorFilter(Color.argb(overlayAlpha, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);
                 d.draw(canvas);
+                d.clearColorFilter();
             }
+            canvas.restore();
         }
 
         canvas.restore();
diff --git a/src/com/android/launcher2/LauncherAppWidgetHostView.java b/src/com/android/launcher2/LauncherAppWidgetHostView.java
index 0dd1d83..099a676 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHostView.java
@@ -18,6 +18,7 @@
 
 import android.appwidget.AppWidgetHostView;
 import android.content.Context;
+import android.content.res.Resources;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -39,8 +40,15 @@
     public LauncherAppWidgetHostView(Context context) {
         super(context);
         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        Resources r = context.getResources();
+        // We add necessary padding to the AppWidgetHostView
+        setPadding(r.getDimensionPixelSize(R.dimen.app_widget_padding_left),
+                r.getDimensionPixelSize(R.dimen.app_widget_padding_top),
+                r.getDimensionPixelSize(R.dimen.app_widget_padding_right),
+                r.getDimensionPixelSize(R.dimen.app_widget_padding_bottom));
     }
-    
+
     @Override
     protected View getErrorView() {
         return mInflater.inflate(R.layout.appwidget_error, this, false);
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index bd41e02..79f647a 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -113,8 +113,8 @@
     protected int mPageLayoutWidthGap;
     protected int mPageLayoutHeightGap;
     protected int mPageLayoutMaxHeight;
-    protected int mCellCountX = -1;
-    protected int mCellCountY = -1;
+    protected int mCellCountX = 0;
+    protected int mCellCountY = 0;
     protected boolean mCenterPagesVertically;
     protected boolean mAllowOverScroll = true;
     protected int mUnboundedScrollX;