1d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenpackage com.android.launcher2;
2d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
3d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.AnimatorSet;
4d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.ObjectAnimator;
5d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.PropertyValuesHolder;
6d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.ValueAnimator;
7d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener;
80cf2a7c3eeb75cbd532b011524140a4b963f2c93Adam Cohenimport android.appwidget.AppWidgetHostView;
9d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.appwidget.AppWidgetProviderInfo;
10d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.content.Context;
110cf2a7c3eeb75cbd532b011524140a4b963f2c93Adam Cohenimport android.graphics.Rect;
12d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.view.Gravity;
13d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.widget.FrameLayout;
14d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport android.widget.ImageView;
15d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
16d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenimport com.android.launcher.R;
17d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
18d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohenpublic class AppWidgetResizeFrame extends FrameLayout {
19d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private LauncherAppWidgetHostView mWidgetView;
20d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private CellLayout mCellLayout;
216788269814a678af976dfc7d6135993e172ce586Adam Cohen    private DragLayer mDragLayer;
226788269814a678af976dfc7d6135993e172ce586Adam Cohen    private Workspace mWorkspace;
23d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private ImageView mLeftHandle;
24d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private ImageView mRightHandle;
251b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    private ImageView mTopHandle;
26d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private ImageView mBottomHandle;
27d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
28d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private boolean mLeftBorderActive;
29d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private boolean mRightBorderActive;
30d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private boolean mTopBorderActive;
31d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private boolean mBottomBorderActive;
32d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
3337b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen    private int mWidgetPaddingLeft;
3437b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen    private int mWidgetPaddingRight;
3537b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen    private int mWidgetPaddingTop;
3637b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen    private int mWidgetPaddingBottom;
3737b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen
38d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mBaselineWidth;
39d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mBaselineHeight;
40d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mBaselineX;
41d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mBaselineY;
42d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mResizeMode;
433cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen
44d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mRunningHInc;
45d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mRunningVInc;
46d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mMinHSpan;
47d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mMinVSpan;
48d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mDeltaX;
49d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    private int mDeltaY;
50bebf042666cffe52039b875a549a582abd78a431Adam Cohen    private int mDeltaXAddOn;
51bebf042666cffe52039b875a549a582abd78a431Adam Cohen    private int mDeltaYAddOn;
521b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen
533cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen    private int mBackgroundPadding;
543cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen    private int mTouchTargetWidth;
55d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
564459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen    private int mTopTouchRegionAdjustment = 0;
574459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen    private int mBottomTouchRegionAdjustment = 0;
584459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen
59bebf042666cffe52039b875a549a582abd78a431Adam Cohen    int[] mDirectionVector = new int[2];
60e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen    int[] mLastDirectionVector = new int[2];
61d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
62d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    final int SNAP_DURATION = 150;
633cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen    final int BACKGROUND_PADDING = 24;
64e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen    final float DIMMED_HANDLE_ALPHA = 0f;
65e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen    final float RESIZE_THRESHOLD = 0.66f;
66d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
679e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen    private static Rect mTmpRect = new Rect();
689e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen
691b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    public static final int LEFT = 0;
701b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    public static final int TOP = 1;
711b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    public static final int RIGHT = 2;
721b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    public static final int BOTTOM = 3;
731b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen
74cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen    private Launcher mLauncher;
75cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen
763a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka    public AppWidgetResizeFrame(Context context,
776788269814a678af976dfc7d6135993e172ce586Adam Cohen            LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) {
78d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
79d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        super(context);
80cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen        mLauncher = (Launcher) context;
81d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mCellLayout = cellLayout;
82d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mWidgetView = widgetView;
8327c09b05d3ed2a4ce9d53140216aba998727a569Adam Cohen        mResizeMode = widgetView.getAppWidgetInfo().resizeMode;
846788269814a678af976dfc7d6135993e172ce586Adam Cohen        mDragLayer = dragLayer;
856788269814a678af976dfc7d6135993e172ce586Adam Cohen        mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
863cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen
87d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
882f093b6ad185967c129781526060288e983bc58aAdam Cohen        int[] result = Launcher.getMinSpanForWidget(mLauncher, info);
89d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mMinHSpan = result[0];
90d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mMinVSpan = result[1];
91d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
923cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        setBackgroundResource(R.drawable.widget_resize_frame_holo);
93d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        setPadding(0, 0, 0, 0);
94d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
95d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        LayoutParams lp;
96d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mLeftHandle = new ImageView(context);
973cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        mLeftHandle.setImageResource(R.drawable.widget_resize_handle_left);
98d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
99cc11f742586b57c576026b7756a46209fe793ea1Fabrice Di Meglio                Gravity.START | Gravity.CENTER_VERTICAL);
100d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        addView(mLeftHandle, lp);
101d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
102d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mRightHandle = new ImageView(context);
1033cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        mRightHandle.setImageResource(R.drawable.widget_resize_handle_right);
104d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
105cc11f742586b57c576026b7756a46209fe793ea1Fabrice Di Meglio                Gravity.END | Gravity.CENTER_VERTICAL);
106d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        addView(mRightHandle, lp);
107d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
108d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mTopHandle = new ImageView(context);
1093cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        mTopHandle.setImageResource(R.drawable.widget_resize_handle_top);
110d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
111d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                Gravity.CENTER_HORIZONTAL | Gravity.TOP);
112d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        addView(mTopHandle, lp);
113d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
114d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mBottomHandle = new ImageView(context);
1153cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        mBottomHandle.setImageResource(R.drawable.widget_resize_handle_bottom);
116d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
117d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
118d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        addView(mBottomHandle, lp);
119d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
1200cf2a7c3eeb75cbd532b011524140a4b963f2c93Adam Cohen        Rect p = AppWidgetHostView.getDefaultPaddingForWidget(context,
1210cf2a7c3eeb75cbd532b011524140a4b963f2c93Adam Cohen                widgetView.getAppWidgetInfo().provider, null);
12282ebbd2a2f9ae5cb0a9d47f2f3a4293e4d0292d7Adam Cohen        mWidgetPaddingLeft = p.left;
12382ebbd2a2f9ae5cb0a9d47f2f3a4293e4d0292d7Adam Cohen        mWidgetPaddingTop = p.top;
12482ebbd2a2f9ae5cb0a9d47f2f3a4293e4d0292d7Adam Cohen        mWidgetPaddingRight = p.right;
12582ebbd2a2f9ae5cb0a9d47f2f3a4293e4d0292d7Adam Cohen        mWidgetPaddingBottom = p.bottom;
12637b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen
127d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
128d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mTopHandle.setVisibility(GONE);
129d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mBottomHandle.setVisibility(GONE);
130d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
131d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mLeftHandle.setVisibility(GONE);
132d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mRightHandle.setVisibility(GONE);
1333cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        }
1343cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen
135cbf47e38e24cc0d63b4bd3f345c050216f06f404Adam Cohen        final float density = mLauncher.getResources().getDisplayMetrics().density;
1363cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        mBackgroundPadding = (int) Math.ceil(density * BACKGROUND_PADDING);
1373cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        mTouchTargetWidth = 2 * mBackgroundPadding;
138bebf042666cffe52039b875a549a582abd78a431Adam Cohen
139bebf042666cffe52039b875a549a582abd78a431Adam Cohen        // When we create the resize frame, we first mark all cells as unoccupied. The appropriate
140bebf042666cffe52039b875a549a582abd78a431Adam Cohen        // cells (same if not resized, or different) will be marked as occupied when the resize
141bebf042666cffe52039b875a549a582abd78a431Adam Cohen        // frame is dismissed.
142bebf042666cffe52039b875a549a582abd78a431Adam Cohen        mCellLayout.markCellsAsUnoccupiedForView(mWidgetView);
143d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
144d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
145d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    public boolean beginResizeIfPointInRegion(int x, int y) {
146d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        boolean horizontalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0;
147d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        boolean verticalActive = (mResizeMode & AppWidgetProviderInfo.RESIZE_VERTICAL) != 0;
1484459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen
1493cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        mLeftBorderActive = (x < mTouchTargetWidth) && horizontalActive;
1503cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        mRightBorderActive = (x > getWidth() - mTouchTargetWidth) && horizontalActive;
1514459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen        mTopBorderActive = (y < mTouchTargetWidth + mTopTouchRegionAdjustment) && verticalActive;
1524459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen        mBottomBorderActive = (y > getHeight() - mTouchTargetWidth + mBottomTouchRegionAdjustment)
1534459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen                && verticalActive;
154d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
155d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        boolean anyBordersActive = mLeftBorderActive || mRightBorderActive
156d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                || mTopBorderActive || mBottomBorderActive;
157d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
158d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mBaselineWidth = getMeasuredWidth();
159d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mBaselineHeight = getMeasuredHeight();
160d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mBaselineX = getLeft();
161d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        mBaselineY = getTop();
162d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
163d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (anyBordersActive) {
1643cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen            mLeftHandle.setAlpha(mLeftBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
1653cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen            mRightHandle.setAlpha(mRightBorderActive ? 1.0f :DIMMED_HANDLE_ALPHA);
1663cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen            mTopHandle.setAlpha(mTopBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
1673cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen            mBottomHandle.setAlpha(mBottomBorderActive ? 1.0f : DIMMED_HANDLE_ALPHA);
168d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
169d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        return anyBordersActive;
170d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
171d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
1721b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    /**
1731b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     *  Here we bound the deltas such that the frame cannot be stretched beyond the extents
1741b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     *  of the CellLayout, and such that the frame's borders can't cross.
1751b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     */
176d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    public void updateDeltas(int deltaX, int deltaY) {
177d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mLeftBorderActive) {
178d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mDeltaX = Math.max(-mBaselineX, deltaX);
1793cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen            mDeltaX = Math.min(mBaselineWidth - 2 * mTouchTargetWidth, mDeltaX);
180d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        } else if (mRightBorderActive) {
1816788269814a678af976dfc7d6135993e172ce586Adam Cohen            mDeltaX = Math.min(mDragLayer.getWidth() - (mBaselineX + mBaselineWidth), deltaX);
1823cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen            mDeltaX = Math.max(-mBaselineWidth + 2 * mTouchTargetWidth, mDeltaX);
183d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
184d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
185d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mTopBorderActive) {
186d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mDeltaY = Math.max(-mBaselineY, deltaY);
1873cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen            mDeltaY = Math.min(mBaselineHeight - 2 * mTouchTargetWidth, mDeltaY);
188d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        } else if (mBottomBorderActive) {
1896788269814a678af976dfc7d6135993e172ce586Adam Cohen            mDeltaY = Math.min(mDragLayer.getHeight() - (mBaselineY + mBaselineHeight), deltaY);
1903cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen            mDeltaY = Math.max(-mBaselineHeight + 2 * mTouchTargetWidth, mDeltaY);
191d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
192d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
193d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
194bebf042666cffe52039b875a549a582abd78a431Adam Cohen    public void visualizeResizeForDelta(int deltaX, int deltaY) {
195bebf042666cffe52039b875a549a582abd78a431Adam Cohen        visualizeResizeForDelta(deltaX, deltaY, false);
196bebf042666cffe52039b875a549a582abd78a431Adam Cohen    }
197bebf042666cffe52039b875a549a582abd78a431Adam Cohen
1981b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    /**
1991b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     *  Based on the deltas, we resize the frame, and, if needed, we resize the widget.
2001b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     */
201bebf042666cffe52039b875a549a582abd78a431Adam Cohen    private void visualizeResizeForDelta(int deltaX, int deltaY, boolean onDismiss) {
202d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        updateDeltas(deltaX, deltaY);
2036788269814a678af976dfc7d6135993e172ce586Adam Cohen        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
2046788269814a678af976dfc7d6135993e172ce586Adam Cohen
205d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mLeftBorderActive) {
206d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.x = mBaselineX + mDeltaX;
207d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.width = mBaselineWidth - mDeltaX;
208d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        } else if (mRightBorderActive) {
209d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.width = mBaselineWidth + mDeltaX;
210d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
211d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
212d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mTopBorderActive) {
213d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.y = mBaselineY + mDeltaY;
214d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.height = mBaselineHeight - mDeltaY;
215d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        } else if (mBottomBorderActive) {
216d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.height = mBaselineHeight + mDeltaY;
217d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
218d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
219bebf042666cffe52039b875a549a582abd78a431Adam Cohen        resizeWidgetIfNeeded(onDismiss);
220d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        requestLayout();
221d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
222d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
2231b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    /**
2241b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     *  Based on the current deltas, we determine if and how to resize the widget.
2251b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     */
226bebf042666cffe52039b875a549a582abd78a431Adam Cohen    private void resizeWidgetIfNeeded(boolean onDismiss) {
227d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap();
228d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap();
229d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
230bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int deltaX = mDeltaX + mDeltaXAddOn;
231bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int deltaY = mDeltaY + mDeltaYAddOn;
232bebf042666cffe52039b875a549a582abd78a431Adam Cohen
233bebf042666cffe52039b875a549a582abd78a431Adam Cohen        float hSpanIncF = 1.0f * deltaX / xThreshold - mRunningHInc;
234bebf042666cffe52039b875a549a582abd78a431Adam Cohen        float vSpanIncF = 1.0f * deltaY / yThreshold - mRunningVInc;
235e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen
236e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen        int hSpanInc = 0;
237e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen        int vSpanInc = 0;
238d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        int cellXInc = 0;
239d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        int cellYInc = 0;
240d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
241bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int countX = mCellLayout.getCountX();
242bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int countY = mCellLayout.getCountY();
243bebf042666cffe52039b875a549a582abd78a431Adam Cohen
244e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen        if (Math.abs(hSpanIncF) > RESIZE_THRESHOLD) {
245e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen            hSpanInc = Math.round(hSpanIncF);
246e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen        }
247e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen        if (Math.abs(vSpanIncF) > RESIZE_THRESHOLD) {
248e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen            vSpanInc = Math.round(vSpanIncF);
249e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen        }
250e4b7729b9d6343b4e7e0905e117e5ac469727cbeAdam Cohen
251bebf042666cffe52039b875a549a582abd78a431Adam Cohen        if (!onDismiss && (hSpanInc == 0 && vSpanInc == 0)) return;
252d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
253d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
254d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mWidgetView.getLayoutParams();
2551b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen
256bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int spanX = lp.cellHSpan;
257bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int spanY = lp.cellVSpan;
258bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int cellX = lp.useTmpCoords ? lp.tmpCellX : lp.cellX;
259bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int cellY = lp.useTmpCoords ? lp.tmpCellY : lp.cellY;
260bebf042666cffe52039b875a549a582abd78a431Adam Cohen
261bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int hSpanDelta = 0;
262bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int vSpanDelta = 0;
263bebf042666cffe52039b875a549a582abd78a431Adam Cohen
2641b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        // For each border, we bound the resizing based on the minimum width, and the maximum
2651b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        // expandability.
266d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mLeftBorderActive) {
267bebf042666cffe52039b875a549a582abd78a431Adam Cohen            cellXInc = Math.max(-cellX, hSpanInc);
268d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            cellXInc = Math.min(lp.cellHSpan - mMinHSpan, cellXInc);
269d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            hSpanInc *= -1;
270bebf042666cffe52039b875a549a582abd78a431Adam Cohen            hSpanInc = Math.min(cellX, hSpanInc);
271d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc);
272bebf042666cffe52039b875a549a582abd78a431Adam Cohen            hSpanDelta = -hSpanInc;
273bebf042666cffe52039b875a549a582abd78a431Adam Cohen
274d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        } else if (mRightBorderActive) {
275bebf042666cffe52039b875a549a582abd78a431Adam Cohen            hSpanInc = Math.min(countX - (cellX + spanX), hSpanInc);
276d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            hSpanInc = Math.max(-(lp.cellHSpan - mMinHSpan), hSpanInc);
277bebf042666cffe52039b875a549a582abd78a431Adam Cohen            hSpanDelta = hSpanInc;
278d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
279d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
280d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mTopBorderActive) {
281bebf042666cffe52039b875a549a582abd78a431Adam Cohen            cellYInc = Math.max(-cellY, vSpanInc);
282d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            cellYInc = Math.min(lp.cellVSpan - mMinVSpan, cellYInc);
283d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            vSpanInc *= -1;
284bebf042666cffe52039b875a549a582abd78a431Adam Cohen            vSpanInc = Math.min(cellY, vSpanInc);
285d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc);
286bebf042666cffe52039b875a549a582abd78a431Adam Cohen            vSpanDelta = -vSpanInc;
287d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        } else if (mBottomBorderActive) {
288bebf042666cffe52039b875a549a582abd78a431Adam Cohen            vSpanInc = Math.min(countY - (cellY + spanY), vSpanInc);
289d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            vSpanInc = Math.max(-(lp.cellVSpan - mMinVSpan), vSpanInc);
290bebf042666cffe52039b875a549a582abd78a431Adam Cohen            vSpanDelta = vSpanInc;
291d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
292d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
293bebf042666cffe52039b875a549a582abd78a431Adam Cohen        mDirectionVector[0] = 0;
294bebf042666cffe52039b875a549a582abd78a431Adam Cohen        mDirectionVector[1] = 0;
295d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        // Update the widget's dimensions and position according to the deltas computed above
296d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mLeftBorderActive || mRightBorderActive) {
297bebf042666cffe52039b875a549a582abd78a431Adam Cohen            spanX += hSpanInc;
298bebf042666cffe52039b875a549a582abd78a431Adam Cohen            cellX += cellXInc;
299e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen            if (hSpanDelta != 0) {
300e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen                mDirectionVector[0] = mLeftBorderActive ? -1 : 1;
301e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen            }
302d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
303d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
304d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (mTopBorderActive || mBottomBorderActive) {
305bebf042666cffe52039b875a549a582abd78a431Adam Cohen            spanY += vSpanInc;
306bebf042666cffe52039b875a549a582abd78a431Adam Cohen            cellY += cellYInc;
307e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen            if (vSpanDelta != 0) {
308e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen                mDirectionVector[1] = mTopBorderActive ? -1 : 1;
309e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen            }
310d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
311d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
312bebf042666cffe52039b875a549a582abd78a431Adam Cohen        if (!onDismiss && vSpanDelta == 0 && hSpanDelta == 0) return;
313bebf042666cffe52039b875a549a582abd78a431Adam Cohen
314e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen        // We always want the final commit to match the feedback, so we make sure to use the
315e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen        // last used direction vector when committing the resize / reorder.
316e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen        if (onDismiss) {
317e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen            mDirectionVector[0] = mLastDirectionVector[0];
318e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen            mDirectionVector[1] = mLastDirectionVector[1];
319e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen        } else {
320e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen            mLastDirectionVector[0] = mDirectionVector[0];
321e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen            mLastDirectionVector[1] = mDirectionVector[1];
322e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen        }
323e0489500d2a2cf410cb3cb687cbc59e966d7084eAdam Cohen
324bebf042666cffe52039b875a549a582abd78a431Adam Cohen        if (mCellLayout.createAreaForResize(cellX, cellY, spanX, spanY, mWidgetView,
325bebf042666cffe52039b875a549a582abd78a431Adam Cohen                mDirectionVector, onDismiss)) {
326bebf042666cffe52039b875a549a582abd78a431Adam Cohen            lp.tmpCellX = cellX;
327bebf042666cffe52039b875a549a582abd78a431Adam Cohen            lp.tmpCellY = cellY;
328bebf042666cffe52039b875a549a582abd78a431Adam Cohen            lp.cellHSpan = spanX;
329bebf042666cffe52039b875a549a582abd78a431Adam Cohen            lp.cellVSpan = spanY;
330bebf042666cffe52039b875a549a582abd78a431Adam Cohen            mRunningVInc += vSpanDelta;
331bebf042666cffe52039b875a549a582abd78a431Adam Cohen            mRunningHInc += hSpanDelta;
332a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen            if (!onDismiss) {
333a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen                updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY);
334a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen            }
335bebf042666cffe52039b875a549a582abd78a431Adam Cohen        }
3366788269814a678af976dfc7d6135993e172ce586Adam Cohen        mWidgetView.requestLayout();
337d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
338d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
339a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen    static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher,
340a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen            int spanX, int spanY) {
3419e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen
3429e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen        getWidgetSizeRanges(launcher, spanX, spanY, mTmpRect);
3439e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen        widgetView.updateAppWidgetSize(null, mTmpRect.left, mTmpRect.top,
3449e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen                mTmpRect.right, mTmpRect.bottom);
3459e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen    }
3469e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen
3479e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen    static Rect getWidgetSizeRanges(Launcher launcher, int spanX, int spanY, Rect rect) {
3489e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen        if (rect == null) {
3499e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen            rect = new Rect();
3509e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen        }
351a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        Rect landMetrics = Workspace.getCellLayoutMetrics(launcher, CellLayout.LANDSCAPE);
352a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        Rect portMetrics = Workspace.getCellLayoutMetrics(launcher, CellLayout.PORTRAIT);
353a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        final float density = launcher.getResources().getDisplayMetrics().density;
354a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen
355a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        // Compute landscape size
356a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        int cellWidth = landMetrics.left;
357a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        int cellHeight = landMetrics.top;
358a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        int widthGap = landMetrics.right;
359a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        int heightGap = landMetrics.bottom;
360a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        int landWidth = (int) ((spanX * cellWidth + (spanX - 1) * widthGap) / density);
361a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        int landHeight = (int) ((spanY * cellHeight + (spanY - 1) * heightGap) / density);
362a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen
363a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        // Compute portrait size
364a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        cellWidth = portMetrics.left;
365a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        cellHeight = portMetrics.top;
366a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        widthGap = portMetrics.right;
367a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        heightGap = portMetrics.bottom;
368a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        int portWidth = (int) ((spanX * cellWidth + (spanX - 1) * widthGap) / density);
369a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen        int portHeight = (int) ((spanY * cellHeight + (spanY - 1) * heightGap) / density);
3709e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen        rect.set(portWidth, landHeight, landWidth, portHeight);
3719e05a5ea951b4d5ffce324da8dd0656353306e6fAdam Cohen        return rect;
372a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen    }
373a897f397e553826f327d853d5728d0e1d24513a6Adam Cohen
3741b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen    /**
3751b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     * This is the final step of the resize. Here we save the new widget size and position
3761b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     * to LauncherModel and animate the resize frame.
3771b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen     */
378bebf042666cffe52039b875a549a582abd78a431Adam Cohen    public void commitResize() {
379bebf042666cffe52039b875a549a582abd78a431Adam Cohen        resizeWidgetIfNeeded(true);
380bebf042666cffe52039b875a549a582abd78a431Adam Cohen        requestLayout();
381bebf042666cffe52039b875a549a582abd78a431Adam Cohen    }
382d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
383bebf042666cffe52039b875a549a582abd78a431Adam Cohen    public void onTouchUp() {
384bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int xThreshold = mCellLayout.getCellWidth() + mCellLayout.getWidthGap();
385bebf042666cffe52039b875a549a582abd78a431Adam Cohen        int yThreshold = mCellLayout.getCellHeight() + mCellLayout.getHeightGap();
386bebf042666cffe52039b875a549a582abd78a431Adam Cohen
387bebf042666cffe52039b875a549a582abd78a431Adam Cohen        mDeltaXAddOn = mRunningHInc * xThreshold;
388bebf042666cffe52039b875a549a582abd78a431Adam Cohen        mDeltaYAddOn = mRunningVInc * yThreshold;
389bebf042666cffe52039b875a549a582abd78a431Adam Cohen        mDeltaX = 0;
390bebf042666cffe52039b875a549a582abd78a431Adam Cohen        mDeltaY = 0;
391d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
392d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        post(new Runnable() {
393bebf042666cffe52039b875a549a582abd78a431Adam Cohen            @Override
394d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            public void run() {
395d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                snapToWidget(true);
396d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            }
397d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        });
398d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
399d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
400d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    public void snapToWidget(boolean animate) {
4016788269814a678af976dfc7d6135993e172ce586Adam Cohen        final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
4026a0393666a75b4cd352ac73a027d9cbcc539f6c2Craig Mautner        int xOffset = mCellLayout.getLeft() + mCellLayout.getPaddingLeft()
4036a0393666a75b4cd352ac73a027d9cbcc539f6c2Craig Mautner                + mDragLayer.getPaddingLeft() - mWorkspace.getScrollX();
4046a0393666a75b4cd352ac73a027d9cbcc539f6c2Craig Mautner        int yOffset = mCellLayout.getTop() + mCellLayout.getPaddingTop()
4056a0393666a75b4cd352ac73a027d9cbcc539f6c2Craig Mautner                + mDragLayer.getPaddingTop() - mWorkspace.getScrollY();
406d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
40737b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen        int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding - mWidgetPaddingLeft -
40837b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen                mWidgetPaddingRight;
40937b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen        int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding - mWidgetPaddingTop -
41037b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen                mWidgetPaddingBottom;
41137b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen
41237b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen        int newX = mWidgetView.getLeft() - mBackgroundPadding + xOffset + mWidgetPaddingLeft;
41337b59ff9aa601d75392341e45d61bbb5c408439fAdam Cohen        int newY = mWidgetView.getTop() - mBackgroundPadding + yOffset + mWidgetPaddingTop;
4143cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen
4154459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen        // We need to make sure the frame's touchable regions lie fully within the bounds of the
4164459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen        // DragLayer. We allow the actual handles to be clipped, but we shift the touch regions
4174459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen        // down accordingly to provide a proper touch target.
4183cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        if (newY < 0) {
4194459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen            // In this case we shift the touch region down to start at the top of the DragLayer
4204459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen            mTopTouchRegionAdjustment = -newY;
4214459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen        } else {
4224459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen            mTopTouchRegionAdjustment = 0;
4233cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        }
4246788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (newY + newHeight > mDragLayer.getHeight()) {
4254459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen            // In this case we shift the touch region up to end at the bottom of the DragLayer
4264459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen            mBottomTouchRegionAdjustment = -(newY + newHeight - mDragLayer.getHeight());
4274459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen        } else {
4284459d6b4db75c49f25ac6a43925a8ea212113218Adam Cohen            mBottomTouchRegionAdjustment = 0;
4293cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen        }
4303cba722d4745b29a47ebc6a472dd921e5c9d7367Adam Cohen
431d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        if (!animate) {
432d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.width = newWidth;
433d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.height = newHeight;
434d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.x = newX;
435d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            lp.y = newY;
436d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mLeftHandle.setAlpha(1.0f);
437d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mRightHandle.setAlpha(1.0f);
438d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mTopHandle.setAlpha(1.0f);
439d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            mBottomHandle.setAlpha(1.0f);
440d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            requestLayout();
441d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        } else {
442d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", lp.width, newWidth);
4431b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", lp.height,
4441b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen                    newHeight);
445d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", lp.x, newX);
446d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", lp.y, newY);
447f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka            ObjectAnimator oa =
448f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka                    LauncherAnimUtils.ofPropertyValuesHolder(lp, this, width, height, x, y);
4492ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka            ObjectAnimator leftOa = LauncherAnimUtils.ofFloat(mLeftHandle, "alpha", 1.0f);
4502ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka            ObjectAnimator rightOa = LauncherAnimUtils.ofFloat(mRightHandle, "alpha", 1.0f);
4512ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka            ObjectAnimator topOa = LauncherAnimUtils.ofFloat(mTopHandle, "alpha", 1.0f);
4522ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka            ObjectAnimator bottomOa = LauncherAnimUtils.ofFloat(mBottomHandle, "alpha", 1.0f);
453d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            oa.addUpdateListener(new AnimatorUpdateListener() {
454d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                public void onAnimationUpdate(ValueAnimator animation) {
455d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                    requestLayout();
456d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                }
457d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            });
4582ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka            AnimatorSet set = LauncherAnimUtils.createAnimatorSet();
459d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            if (mResizeMode == AppWidgetProviderInfo.RESIZE_VERTICAL) {
460d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                set.playTogether(oa, topOa, bottomOa);
461d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            } else if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
462d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                set.playTogether(oa, leftOa, rightOa);
463d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            } else {
464d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen                set.playTogether(oa, leftOa, rightOa, topOa, bottomOa);
465d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            }
466d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
467d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            set.setDuration(SNAP_DURATION);
468d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen            set.start();
469d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        }
470d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
471d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen}
472