131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.Animator;
20716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.AnimatorListenerAdapter;
21716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.TimeInterpolator;
22716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator;
23716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
25716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.content.res.Resources;
26360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.Canvas;
276788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect;
28360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chungimport android.graphics.drawable.Drawable;
2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.KeyEvent;
310e26059548e429e5d1c973bebe4c561bead2926fMichael Jurkaimport android.view.MotionEvent;
32ea3763c2672f77539538af8cdd395ad97058eaabRomain Guyimport android.view.View;
338b805b17158886035b38261eb611d8641701ae43Michael Jurkaimport android.view.ViewGroup;
3476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.ViewParent;
353371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent;
363371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager;
3783ca480941b3dd635b62347008fc8d7859d82002Winson Chungimport android.view.accessibility.AccessibilityNodeInfo;
38716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.view.animation.DecelerateInterpolator;
393e8f811f31a2275e778244427271f77f4116c08bAdam Cohenimport android.view.animation.Interpolator;
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout;
41ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohenimport android.widget.TextView;
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport com.android.launcher.R;
44716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
451d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohenimport java.util.ArrayList;
466788269814a678af976dfc7d6135993e172ce586Adam Cohen
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
480e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
508b805b17158886035b38261eb611d8641701ae43Michael Jurkapublic class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChangeListener {
51120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private DragController mDragController;
52120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private int[] mTmpXY = new int[2];
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
54716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private int mXDown, mYDown;
55716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private Launcher mLauncher;
56716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
576788269814a678af976dfc7d6135993e172ce586Adam Cohen    // Variables relating to resizing widgets
586788269814a678af976dfc7d6135993e172ce586Adam Cohen    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
596788269814a678af976dfc7d6135993e172ce586Adam Cohen            new ArrayList<AppWidgetResizeFrame>();
606788269814a678af976dfc7d6135993e172ce586Adam Cohen    private AppWidgetResizeFrame mCurrentResizeFrame;
61716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
62716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    // Variables relating to animation of views after drop
63716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private ValueAnimator mDropAnim = null;
648dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private ValueAnimator mFadeOutAnim = null;
658dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    private DragView mDropView = null;
676441de0ec2a71862798dd51180d0811b42edd514Adam Cohen    private int mAnchorViewInitialScrollX = 0;
686441de0ec2a71862798dd51180d0811b42edd514Adam Cohen    private View mAnchorView = null;
698dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
703371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean mHoverPointClosesFolder = false;
713371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private Rect mHitRect = new Rect();
7221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private int mWorkspaceIndex = -1;
73ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private int mQsbIndex = -1;
74ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_DISAPPEAR = 0;
75ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_FADE_OUT = 1;
76ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
776788269814a678af976dfc7d6135993e172ce586Adam Cohen
7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
8031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
820e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
86be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung
87be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        // Disable multitouch across the workspace/all apps/customize tray
88be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        setMotionEventSplittingEnabled(false);
8921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        setChildrenDrawingOrderEnabled(true);
908b805b17158886035b38261eb611d8641701ae43Michael Jurka        setOnHierarchyChangeListener(this);
91360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
92360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        mLeftHoverDrawable = getResources().getDrawable(R.drawable.page_hover_left_holo);
93360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        mRightHoverDrawable = getResources().getDrawable(R.drawable.page_hover_right_holo);
9431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
964c98d9235d164680186180974719f551cf935d08Winson Chung    public void setup(Launcher launcher, DragController controller) {
974c98d9235d164680186180974719f551cf935d08Winson Chung        mLauncher = launcher;
9800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = controller;
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
10076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
10300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
1073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
1083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
1093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return true;
1103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
1113371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
1123371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1133371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
1143371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private boolean isEventOverFolder(Folder folder, MotionEvent ev) {
1153371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        getDescendantRectRelativeToSelf(folder, mHitRect);
1163371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
1173371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return true;
1183371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
1193371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
1203371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
1213371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
12276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
1236788269814a678af976dfc7d6135993e172ce586Adam Cohen        Rect hitRect = new Rect();
1246788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
1256788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
1266788269814a678af976dfc7d6135993e172ce586Adam Cohen
1276788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (AppWidgetResizeFrame child: mResizeFrames) {
1286788269814a678af976dfc7d6135993e172ce586Adam Cohen            child.getHitRect(hitRect);
1296788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (hitRect.contains(x, y)) {
1306788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
1316788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = child;
1326788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mXDown = x;
1336788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mYDown = y;
1346788269814a678af976dfc7d6135993e172ce586Adam Cohen                    requestDisallowInterceptTouchEvent(true);
1356788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
1366788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
1376788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
1386788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
13976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1401d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
1417d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung        if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
1421d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            if (currentFolder.isEditingName()) {
1433371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                if (!isEventOverFolderTextRegion(currentFolder, ev)) {
1441d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen                    currentFolder.dismissEditingName();
14576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                    return true;
1462801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                }
1472801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            }
14876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
1491d9af7d1e75bad13bb10ad37f5900ed59882622eAdam Cohen            getDescendantRectRelativeToSelf(currentFolder, hitRect);
1503371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            if (!isEventOverFolder(currentFolder, ev)) {
15176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                mLauncher.closeFolder();
15276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                return true;
15376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            }
1542801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
1556788269814a678af976dfc7d6135993e172ce586Adam Cohen        return false;
1566788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
1576788269814a678af976dfc7d6135993e172ce586Adam Cohen
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
1606788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
16176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            if (handleTouchDown(ev, true)) {
1626788269814a678af976dfc7d6135993e172ce586Adam Cohen                return true;
163d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy            }
1641b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        }
1656788269814a678af976dfc7d6135993e172ce586Adam Cohen        clearAllResizeFrames();
1664db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onInterceptTouchEvent(ev);
16731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
1703371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onInterceptHoverEvent(MotionEvent ev) {
171023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        if (mLauncher == null || mLauncher.getWorkspace() == null) {
172023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka            return false;
173023c71eb3b2bbe63272cb74baaf050c4188c89b0Michael Jurka        }
1743371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
1753371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        if (currentFolder == null) {
1763371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            return false;
1773371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        } else {
1788b805b17158886035b38261eb611d8641701ae43Michael Jurka                AccessibilityManager accessibilityManager = (AccessibilityManager)
1798b805b17158886035b38261eb611d8641701ae43Michael Jurka                        getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
1808b805b17158886035b38261eb611d8641701ae43Michael Jurka            if (accessibilityManager.isTouchExplorationEnabled()) {
1813371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                final int action = ev.getAction();
1823371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                boolean isOverFolder;
1833371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                switch (action) {
1843371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_ENTER:
1853371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        isOverFolder = isEventOverFolder(currentFolder, ev);
1863371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        if (!isOverFolder) {
1873371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
1883371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
1893371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1903371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else if (isOverFolder) {
1913371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = false;
1923371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else {
1933371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
1943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
1953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    case MotionEvent.ACTION_HOVER_MOVE:
1963371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        isOverFolder = isEventOverFolder(currentFolder, ev);
1973371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        if (!isOverFolder && !mHoverPointClosesFolder) {
1983371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            sendTapOutsideFolderAccessibilityEvent(currentFolder.isEditingName());
1993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = true;
2003371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
2013371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else if (isOverFolder) {
2023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            mHoverPointClosesFolder = false;
2033371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        } else {
2043371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                            return true;
2053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                        }
2063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                }
2073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            }
2083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
2093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
2103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2113371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2123371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    private void sendTapOutsideFolderAccessibilityEvent(boolean isEditingName) {
2138b805b17158886035b38261eb611d8641701ae43Michael Jurka        AccessibilityManager accessibilityManager = (AccessibilityManager)
2148b805b17158886035b38261eb611d8641701ae43Michael Jurka                getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
2158b805b17158886035b38261eb611d8641701ae43Michael Jurka        if (accessibilityManager.isEnabled()) {
2163371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            int stringId = isEditingName ? R.string.folder_tap_to_rename : R.string.folder_tap_to_close;
2173371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            AccessibilityEvent event = AccessibilityEvent.obtain(
2183371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen                    AccessibilityEvent.TYPE_VIEW_FOCUSED);
2193371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen            onInitializeAccessibilityEvent(event);
2208b805b17158886035b38261eb611d8641701ae43Michael Jurka            event.getText().add(getContext().getString(stringId));
2218b805b17158886035b38261eb611d8641701ae43Michael Jurka            accessibilityManager.sendAccessibilityEvent(event);
2223371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        }
22383ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
22483ca480941b3dd635b62347008fc8d7859d82002Winson Chung
22583ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
22683ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
22783ca480941b3dd635b62347008fc8d7859d82002Winson Chung        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
22883ca480941b3dd635b62347008fc8d7859d82002Winson Chung        if (currentFolder != null) {
22983ca480941b3dd635b62347008fc8d7859d82002Winson Chung            if (child == currentFolder) {
23083ca480941b3dd635b62347008fc8d7859d82002Winson Chung                return super.onRequestSendAccessibilityEvent(child, event);
23183ca480941b3dd635b62347008fc8d7859d82002Winson Chung            }
23283ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // Skip propagating onRequestSendAccessibilityEvent all for other children
23383ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // when a folder is open
23483ca480941b3dd635b62347008fc8d7859d82002Winson Chung            return false;
23583ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
23683ca480941b3dd635b62347008fc8d7859d82002Winson Chung        return super.onRequestSendAccessibilityEvent(child, event);
23783ca480941b3dd635b62347008fc8d7859d82002Winson Chung    }
23883ca480941b3dd635b62347008fc8d7859d82002Winson Chung
23983ca480941b3dd635b62347008fc8d7859d82002Winson Chung    @Override
24083ca480941b3dd635b62347008fc8d7859d82002Winson Chung    public void addChildrenForAccessibility(ArrayList<View> childrenForAccessibility) {
24183ca480941b3dd635b62347008fc8d7859d82002Winson Chung        Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
24283ca480941b3dd635b62347008fc8d7859d82002Winson Chung        if (currentFolder != null) {
24383ca480941b3dd635b62347008fc8d7859d82002Winson Chung            // Only add the folder as a child for accessibility when it is open
24483ca480941b3dd635b62347008fc8d7859d82002Winson Chung            childrenForAccessibility.add(currentFolder);
24583ca480941b3dd635b62347008fc8d7859d82002Winson Chung        } else {
24683ca480941b3dd635b62347008fc8d7859d82002Winson Chung            super.addChildrenForAccessibility(childrenForAccessibility);
24783ca480941b3dd635b62347008fc8d7859d82002Winson Chung        }
2483371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2493371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2503371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
2513371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    public boolean onHoverEvent(MotionEvent ev) {
2523371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // If we've received this, we've already done the necessary handling
2533371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        // in onInterceptHoverEvent. Return true to consume the event.
2543371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen        return false;
2553371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    }
2563371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen
2573371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen    @Override
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
2596788269814a678af976dfc7d6135993e172ce586Adam Cohen        boolean handled = false;
2606788269814a678af976dfc7d6135993e172ce586Adam Cohen        int action = ev.getAction();
2616788269814a678af976dfc7d6135993e172ce586Adam Cohen
2626788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
2636788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
2646788269814a678af976dfc7d6135993e172ce586Adam Cohen
2656788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
2666788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
26776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                if (handleTouchDown(ev, false)) {
2686788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
2696788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
2706788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2716788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2726788269814a678af976dfc7d6135993e172ce586Adam Cohen
2736788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mCurrentResizeFrame != null) {
2746788269814a678af976dfc7d6135993e172ce586Adam Cohen            handled = true;
2756788269814a678af976dfc7d6135993e172ce586Adam Cohen            switch (action) {
2766788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_MOVE:
2776788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
2786788269814a678af976dfc7d6135993e172ce586Adam Cohen                    break;
2796788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_CANCEL:
2806788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_UP:
281bebf042666cffe52039b875a549a582abd78a431Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
282bebf042666cffe52039b875a549a582abd78a431Adam Cohen                    mCurrentResizeFrame.onTouchUp();
2836788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = null;
2846788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2856788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2866788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (handled) return true;
2874db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onTouchEvent(ev);
28891a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy    }
289ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
29035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
29135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Determine the rect of the descendant in this DragLayer's coordinates
29235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
29335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant whose coordinates we want to find.
29435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param r The rect into which to place the results.
29535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer.
29635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
297ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen    public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
298716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[0] = 0;
299716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mTmpXY[1] = 0;
300ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
3018dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        r.set(mTmpXY[0], mTmpXY[1],
3028dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mTmpXY[0] + descendant.getWidth(), mTmpXY[1] + descendant.getHeight());
303ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        return scale;
304716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
30576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
306307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen    public float getLocationInDragLayer(View child, int[] loc) {
30735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[0] = 0;
30835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        loc[1] = 0;
309307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        return getDescendantCoordRelativeToSelf(child, loc);
31035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    }
31135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen
31235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen    /**
31335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * Given a coordinate relative to the descendant, find the coordinate in this DragLayer's
31435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * coordinates.
31535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     *
31635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param descendant The descendant to which the passed coordinate is relative.
31735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     * @param coord The coordinate that we want mapped.
318307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
319307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         this scale factor is assumed to be equal in X and Y, and so if at any point this
320307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen     *         assumption fails, we will need to return a pair of scale factors.
32135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen     */
322b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
323557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = 1.0f;
324557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float[] pt = {coord[0], coord[1]};
325557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        descendant.getMatrix().mapPoints(pt);
326557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        scale *= descendant.getScaleX();
327557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        pt[0] += descendant.getLeft();
328557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        pt[1] += descendant.getTop();
32976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        ViewParent viewParent = descendant.getParent();
33076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        while (viewParent instanceof View && viewParent != this) {
33176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            final View view = (View)viewParent;
332557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            view.getMatrix().mapPoints(pt);
333557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            scale *= view.getScaleX();
334557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            pt[0] += view.getLeft() - view.getScrollX();
335557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            pt[1] += view.getTop() - view.getScrollY();
33676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            viewParent = view.getParent();
33776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
338fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        coord[0] = (int) Math.round(pt[0]);
339fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen        coord[1] = (int) Math.round(pt[1]);
340557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        return scale;
34176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
34276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
3433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    public void getViewRectRelativeToSelf(View v, Rect r) {
3443e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int[] loc = new int[2];
3458dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        getLocationInWindow(loc);
3463e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int x = loc[0];
3473e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int y = loc[1];
348716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
3498dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        v.getLocationInWindow(loc);
3503e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vX = loc[0];
3513e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int vY = loc[1];
352716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
3533e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int left = vX - x;
3543e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        int top = vY - y;
3553e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        r.set(left, top, left + v.getMeasuredWidth(), top + v.getMeasuredHeight());
356716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
357716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
358ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @Override
359ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
360ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mDragController.dispatchUnhandledMove(focused, direction);
361ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
362120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
3636788269814a678af976dfc7d6135993e172ce586Adam Cohen    public static class LayoutParams extends FrameLayout.LayoutParams {
3646788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int x, y;
3656788269814a678af976dfc7d6135993e172ce586Adam Cohen        public boolean customPosition = false;
3666788269814a678af976dfc7d6135993e172ce586Adam Cohen
3676788269814a678af976dfc7d6135993e172ce586Adam Cohen        /**
3686788269814a678af976dfc7d6135993e172ce586Adam Cohen         * {@inheritDoc}
3696788269814a678af976dfc7d6135993e172ce586Adam Cohen         */
3706788269814a678af976dfc7d6135993e172ce586Adam Cohen        public LayoutParams(int width, int height) {
3716788269814a678af976dfc7d6135993e172ce586Adam Cohen            super(width, height);
3726788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3736788269814a678af976dfc7d6135993e172ce586Adam Cohen
3746788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setWidth(int width) {
3756788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.width = width;
3766788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3776788269814a678af976dfc7d6135993e172ce586Adam Cohen
3786788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getWidth() {
3796788269814a678af976dfc7d6135993e172ce586Adam Cohen            return width;
3806788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3816788269814a678af976dfc7d6135993e172ce586Adam Cohen
3826788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setHeight(int height) {
3836788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.height = height;
3846788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3856788269814a678af976dfc7d6135993e172ce586Adam Cohen
3866788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getHeight() {
3876788269814a678af976dfc7d6135993e172ce586Adam Cohen            return height;
3886788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3896788269814a678af976dfc7d6135993e172ce586Adam Cohen
3906788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setX(int x) {
3916788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.x = x;
3926788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3936788269814a678af976dfc7d6135993e172ce586Adam Cohen
3946788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getX() {
3956788269814a678af976dfc7d6135993e172ce586Adam Cohen            return x;
3966788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
3976788269814a678af976dfc7d6135993e172ce586Adam Cohen
3986788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setY(int y) {
3996788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.y = y;
4006788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4016788269814a678af976dfc7d6135993e172ce586Adam Cohen
4026788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getY() {
4036788269814a678af976dfc7d6135993e172ce586Adam Cohen            return y;
4046788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4056788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4066788269814a678af976dfc7d6135993e172ce586Adam Cohen
4076788269814a678af976dfc7d6135993e172ce586Adam Cohen    protected void onLayout(boolean changed, int l, int t, int r, int b) {
4086788269814a678af976dfc7d6135993e172ce586Adam Cohen        super.onLayout(changed, l, t, r, b);
4096788269814a678af976dfc7d6135993e172ce586Adam Cohen        int count = getChildCount();
4106788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (int i = 0; i < count; i++) {
4116788269814a678af976dfc7d6135993e172ce586Adam Cohen            View child = getChildAt(i);
4126788269814a678af976dfc7d6135993e172ce586Adam Cohen            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
4136788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (flp instanceof LayoutParams) {
4146788269814a678af976dfc7d6135993e172ce586Adam Cohen                final LayoutParams lp = (LayoutParams) flp;
4156788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (lp.customPosition) {
4166788269814a678af976dfc7d6135993e172ce586Adam Cohen                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
4176788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
4186788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
4196788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4206788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4216788269814a678af976dfc7d6135993e172ce586Adam Cohen
4226788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void clearAllResizeFrames() {
4236788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mResizeFrames.size() > 0) {
4246788269814a678af976dfc7d6135993e172ce586Adam Cohen            for (AppWidgetResizeFrame frame: mResizeFrames) {
425bebf042666cffe52039b875a549a582abd78a431Adam Cohen                frame.commitResize();
4266788269814a678af976dfc7d6135993e172ce586Adam Cohen                removeView(frame);
4276788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
4286788269814a678af976dfc7d6135993e172ce586Adam Cohen            mResizeFrames.clear();
4296788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
4306788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4316788269814a678af976dfc7d6135993e172ce586Adam Cohen
4326788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean hasResizeFrames() {
4336788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mResizeFrames.size() > 0;
4346788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4356788269814a678af976dfc7d6135993e172ce586Adam Cohen
4366788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean isWidgetBeingResized() {
4376788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mCurrentResizeFrame != null;
4386788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
4396788269814a678af976dfc7d6135993e172ce586Adam Cohen
4406788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
4416788269814a678af976dfc7d6135993e172ce586Adam Cohen            CellLayout cellLayout) {
4426788269814a678af976dfc7d6135993e172ce586Adam Cohen        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
4433a9fcedbcd235372cd2ab64f825a0b5b3937f59eMichael Jurka                widget, cellLayout, this);
4446788269814a678af976dfc7d6135993e172ce586Adam Cohen
4456788269814a678af976dfc7d6135993e172ce586Adam Cohen        LayoutParams lp = new LayoutParams(-1, -1);
4466788269814a678af976dfc7d6135993e172ce586Adam Cohen        lp.customPosition = true;
4476788269814a678af976dfc7d6135993e172ce586Adam Cohen
4486788269814a678af976dfc7d6135993e172ce586Adam Cohen        addView(resizeFrame, lp);
4496788269814a678af976dfc7d6135993e172ce586Adam Cohen        mResizeFrames.add(resizeFrame);
4506788269814a678af976dfc7d6135993e172ce586Adam Cohen
4516788269814a678af976dfc7d6135993e172ce586Adam Cohen        resizeFrame.snapToWidget(false);
4526788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
453716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
454716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child) {
455557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        animateViewIntoPosition(dragView, child, null);
456557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
457ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen
4587bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
4597bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
4607bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            int duration) {
461b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        Rect r = new Rect();
462b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        getViewRectRelativeToSelf(dragView, r);
463b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromX = r.left;
464b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen        final int fromY = r.top;
465b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen
4667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        animateViewIntoPosition(dragView, fromX, fromY, pos[0], pos[1], alpha, 1, 1, scaleX, scaleY,
467ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                onFinishRunnable, animationEndStyle, duration, null);
468ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
469ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
470557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    public void animateViewIntoPosition(DragView dragView, final View child,
471557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung            final Runnable onFinishAnimationRunnable) {
4726441de0ec2a71862798dd51180d0811b42edd514Adam Cohen        animateViewIntoPosition(dragView, child, -1, onFinishAnimationRunnable, null);
473ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    }
474ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen
475ed51cc9a12c50d12e7d30ed209a49f1a40858043Adam Cohen    public void animateViewIntoPosition(DragView dragView, final View child, int duration,
4766441de0ec2a71862798dd51180d0811b42edd514Adam Cohen            final Runnable onFinishAnimationRunnable, View anchorView) {
477a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka        ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent();
478716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        CellLayout.LayoutParams lp =  (CellLayout.LayoutParams) child.getLayoutParams();
479eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung        parentChildren.measureChild(child);
480716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
4813e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect r = new Rect();
4823e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        getViewRectRelativeToSelf(dragView, r);
483716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
484716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        int coord[] = new int[2];
485307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        float childScale = child.getScaleX();
486307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2);
487307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2);
488eecf02da58adef5486bf0c9ff7127ea891f457a4Winson Chung
4898dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        // Since the child hasn't necessarily been laid out, we force the lp to be updated with
490ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        // the correct coordinates (above) and use these to determine the final location
491557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung        float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
492307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // We need to account for the scale of the child itself, as the above only accounts for
493307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        // for the scale in parents.
494307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen        scale *= childScale;
495ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toX = coord[0];
496ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        int toY = coord[1];
4974497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        if (child instanceof TextView) {
4984497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            TextView tv = (TextView) child;
4994497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn
5004497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // The child may be scaled (always about the center of the view) so to account for it,
5014497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // we have to offset the position by the scaled size.  Once we do that, we can center
5024497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            // the drag view about the scaled child view.
5034497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toY += Math.round(scale * tv.getPaddingTop());
5044497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toY -= dragView.getMeasuredHeight() * (1 - scale) / 2;
5054497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
5064497ebf9a2726e2a7dbb7f3c49389308908f8454Andrew Flynn        } else if (child instanceof FolderIcon) {
507ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Account for holographic blur padding on the drag view
508307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen            toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2;
509307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen            toY -= (1 - scale) * dragView.getMeasuredHeight() / 2;
510ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            // Center in the x coordinate about the target's drawable
511ea359c6aee44c0fe3bb94f7002c3b49208b32b7fWinson Chung            toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
512ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        } else {
513ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
514ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            toX -= (Math.round(scale * (dragView.getMeasuredWidth()
515ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen                    - child.getMeasuredWidth()))) / 2;
516ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        }
517716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
518ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromX = r.left;
519ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen        final int fromY = r.top;
520716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        child.setVisibility(INVISIBLE);
5218dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Runnable onCompleteRunnable = new Runnable() {
5228dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void run() {
5238dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                child.setVisibility(VISIBLE);
524d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                if (onFinishAnimationRunnable != null) {
525d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                    onFinishAnimationRunnable.run();
526d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                }
5278dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
5288dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        };
529ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale,
530d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen                onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
531557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung    }
532557d6ed50cc6560163440aa134870ef0bb11415bWinson Chung
533d41fbf5680750e34335bba6b38298186c144a4b7Adam Cohen    public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
534ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
535ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
536ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen            int animationEndStyle, int duration, View anchorView) {
5378dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        Rect from = new Rect(fromX, fromY, fromX +
5388dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
5393e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
540ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        animateView(view, from, to, finalAlpha, initScaleX, initScaleY, finalScaleX, finalScaleY, duration,
541ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                null, null, onCompleteRunnable, animationEndStyle, anchorView);
5423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
5433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
544b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen    /**
545b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * This method animates a view at the end of a drag and drop animation.
546b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *
547b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param view The view to be animated. This view is drawn directly into DragLayer, and so
548b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        doesn't need to be a child of DragLayer.
549b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param from The initial location of the view. Only the left and top parameters are used.
550b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param to The final location of the view. Only the left and top parameters are used. This
551b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        location doesn't account for scaling, and so should be centered about the desired
552b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        final location (including scaling).
553b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalAlpha The final alpha of the view, in case we want it to fade as it animates.
554b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param finalScale The final scale of the view. The view is scaled about its center.
555b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param duration The duration of the animation.
556b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param motionInterpolator The interpolator to use for the location of the view.
557b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param alphaInterpolator The interpolator to use for the alpha of the view.
558b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param onCompleteRunnable Optional runnable to run on animation completion.
559b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     * @param fadeOut Whether or not to fade out the view once the animation completes. If true,
560b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     *        the runnable will execute after the view is faded out.
5616441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     * @param anchorView If not null, this represents the view which the animated view stays
5626441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        anchored to in case scrolling is currently taking place. Note: currently this is
5636441de0ec2a71862798dd51180d0811b42edd514Adam Cohen     *        only used for the X dimension for the case of the workspace.
564b7e1618c627c6471c565f4f599228648d9e70a10Adam Cohen     */
5657bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung    public void animateView(final DragView view, final Rect from, final Rect to,
5667bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalAlpha, final float initScaleX, final float initScaleY,
5677bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final float finalScaleX, final float finalScaleY, int duration,
5687bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Interpolator motionInterpolator, final Interpolator alphaInterpolator,
5697bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            final Runnable onCompleteRunnable, final int animationEndStyle, View anchorView) {
5707bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
571716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        // Calculate the duration of the animation based on the object's distance
5723e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
5733e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                Math.pow(to.top - from.top, 2));
574716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final Resources res = getResources();
575716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
5763e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
5773e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        // If duration < 0, this is a cue to compute the duration based on the distance
5783e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (duration < 0) {
5793e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
5803e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            if (dist < maxDist) {
5818dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
5823e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
58361b0c69d3fe331d3de338322396d5de691d58613Winson Chung            duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
584716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        }
585716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
586043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Fall back to cubic ease out interpolator for the animation if none is specified
587043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        TimeInterpolator interpolator = null;
5883e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (alphaInterpolator == null || motionInterpolator == null) {
589043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            interpolator = mCubicEaseOutInterpolator;
5903e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        }
591716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
592043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Animate the view
5937bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        final float initAlpha = view.getAlpha();
594043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float dropViewScale = view.getScaleX();
595043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = new AnimatorUpdateListener() {
596043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
597716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
598716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
5997bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int width = view.getMeasuredWidth();
6007bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                final int height = view.getMeasuredHeight();
601716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
6023e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float alphaPercent = alphaInterpolator == null ? percent :
6033e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        alphaInterpolator.getInterpolation(percent);
6043e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                float motionPercent = motionInterpolator == null ? percent :
6053e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                        motionInterpolator.getInterpolation(percent);
606a1cdab039292f3d809528c0e2e38580b37864d8dWinson Chung
6077bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleX = initScaleX * dropViewScale;
6087bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float initialScaleY = initScaleY * dropViewScale;
6097bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleX = finalScaleX * percent + initialScaleX * (1 - percent);
6107bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float scaleY = finalScaleY * percent + initialScaleY * (1 - percent);
6117bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = finalAlpha * alphaPercent + initAlpha * (1 - alphaPercent);
6127bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6137bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromLeft = from.left + (initialScaleX - 1f) * width / 2;
6147bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float fromTop = from.top + (initialScaleY - 1f) * height / 2;
6157bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6167bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int x = (int) (fromLeft + Math.round(((to.left - fromLeft) * motionPercent)));
6177bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int y = (int) (fromTop + Math.round(((to.top - fromTop) * motionPercent)));
6187bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6197bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int xPos = x - mDropView.getScrollX() + (mAnchorView != null
6207bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                        ? (mAnchorViewInitialScrollX - mAnchorView.getScrollX()) : 0);
6217bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                int yPos = y - mDropView.getScrollY();
6227bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
6237bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationX(xPos);
6247bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setTranslationY(yPos);
6257bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleX(scaleX);
6267bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setScaleY(scaleY);
6277bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
628716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            }
629043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
630043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        animateView(view, updateCb, duration, interpolator, onCompleteRunnable, animationEndStyle,
631043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                anchorView);
632043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
633043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
634043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void animateView(final DragView view, AnimatorUpdateListener updateCb, int duration,
635043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            TimeInterpolator interpolator, final Runnable onCompleteRunnable,
636043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final int animationEndStyle, View anchorView) {
637043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Clean up the previous animations
638043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mDropAnim != null) mDropAnim.cancel();
639043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFadeOutAnim != null) mFadeOutAnim.cancel();
640043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
641043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Show the drop view if it was previously hidden
642043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView = view;
643043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.cancelAnimation();
644043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropView.resetLayoutParams();
645043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
646043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Set the anchor view if the page is scrolling
647043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (anchorView != null) {
648043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mAnchorViewInitialScrollX = anchorView.getScrollX();
649043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
650043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mAnchorView = anchorView;
651043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
652043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Create and start the animation
653043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim = new ValueAnimator();
654043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setInterpolator(interpolator);
655043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setDuration(duration);
656043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.setFloatValues(0f, 1f);
657043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        mDropAnim.addUpdateListener(updateCb);
6583e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mDropAnim.addListener(new AnimatorListenerAdapter() {
6593e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            public void onAnimationEnd(Animator animation) {
6608dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                if (onCompleteRunnable != null) {
6618dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    onCompleteRunnable.run();
6628dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                }
663ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                switch (animationEndStyle) {
664ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_DISAPPEAR:
665ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    clearAnimatedView();
666ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
667ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_FADE_OUT:
6688dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                    fadeOutDragView();
669ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
670ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                case ANIMATION_END_REMAIN_VISIBLE:
671ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                    break;
6723e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                }
6733e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
6743e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        });
675716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        mDropAnim.start();
676716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    }
677716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen
678ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public void clearAnimatedView() {
6797bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropAnim != null) {
6807bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung            mDropAnim.cancel();
6817bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
6827bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        if (mDropView != null) {
683043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mDragController.onDeferredEndDrag(mDropView);
6847bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung        }
685ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        mDropView = null;
686ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        invalidate();
687ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
688ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
689ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    public View getAnimatedView() {
690ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        return mDropView;
691ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    }
692ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
6938dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private void fadeOutDragView() {
6948dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim = new ValueAnimator();
6958dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.setDuration(150);
6968dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.setFloatValues(0f, 1f);
6978dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.removeAllUpdateListeners();
6988dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() {
6998dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void onAnimationUpdate(ValueAnimator animation) {
7008dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                final float percent = (Float) animation.getAnimatedValue();
7017bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung
7027bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                float alpha = 1 - percent;
7037bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                mDropView.setAlpha(alpha);
7048dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
7058dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        });
7068dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.addListener(new AnimatorListenerAdapter() {
7078dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            public void onAnimationEnd(Animator animation) {
7087bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                if (mDropView != null) {
709043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mDragController.onDeferredEndDrag(mDropView);
7107bd1bbb509f9569fa18d6b4d33242679fd98bc9bWinson Chung                }
7118dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                mDropView = null;
712ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                invalidate();
7138dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            }
7148dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        });
7158dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mFadeOutAnim.start();
7168dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    }
7178dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
718716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    @Override
7198b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewAdded(View parent, View child) {
72021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
72121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
72221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
72321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
7248b805b17158886035b38261eb611d8641701ae43Michael Jurka    public void onChildViewRemoved(View parent, View child) {
72521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        updateChildIndices();
72621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
72721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
72821b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    private void updateChildIndices() {
72921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        if (mLauncher != null) {
73021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            mWorkspaceIndex = indexOfChild(mLauncher.getWorkspace());
731ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen            mQsbIndex = indexOfChild(mLauncher.getSearchBar());
73221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
73321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
73421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
73521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    @Override
73621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    protected int getChildDrawingOrder(int childCount, int i) {
737e29c55ac322f3386327fa5b61e79b00ba3e5d428Adam Cohen        // TODO: We have turned off this custom drawing order because it now effects touch
738e29c55ac322f3386327fa5b61e79b00ba3e5d428Adam Cohen        // dispatch order. We need to sort that issue out and then decide how to go about this.
739e29c55ac322f3386327fa5b61e79b00ba3e5d428Adam Cohen        if (true || LauncherApplication.isScreenLandscape(getContext()) ||
740e29c55ac322f3386327fa5b61e79b00ba3e5d428Adam Cohen                mWorkspaceIndex == -1 || mQsbIndex == -1 ||
74121b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen                mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
74221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
74321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
74421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen
74521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // This ensures that the workspace is drawn above the hotseat and qsb,
74621b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // except when the workspace is drawing a background gradient, in which
74721b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        // case we want the workspace to stay behind these elements.
748ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        if (i == mQsbIndex) {
74921b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return mWorkspaceIndex;
75021b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        } else if (i == mWorkspaceIndex) {
751ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen            return mQsbIndex;
75221b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        } else {
75321b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen            return i;
75421b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen        }
75521b411074e39fd10cbc8dd0220bb159da4af2c76Adam Cohen    }
756360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
757360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    private boolean mInScrollArea;
758360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    private Drawable mLeftHoverDrawable;
759360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    private Drawable mRightHoverDrawable;
760360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
761360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    void onEnterScrollArea(int direction) {
762360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        mInScrollArea = true;
763360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        invalidate();
764360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    }
765360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
766360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    void onExitScrollArea() {
767360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        mInScrollArea = false;
768360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        invalidate();
769360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    }
770360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
771fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung    /**
772fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung     * Note: this is a reimplementation of View.isLayoutRtl() since that is currently hidden api.
773fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung     */
774f499b916e64ac776c7c57199985e0ec841141eecJohn Spurlock    private boolean isLayoutDirectionRtl() {
775fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
776fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung    }
777fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung
778360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    @Override
779360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    protected void dispatchDraw(Canvas canvas) {
780360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        super.dispatchDraw(canvas);
781360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
782360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        if (mInScrollArea && !LauncherApplication.isScreenLarge()) {
783360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            Workspace workspace = mLauncher.getWorkspace();
784360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            int width = workspace.getWidth();
785360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            Rect childRect = new Rect();
786360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            getDescendantRectRelativeToSelf(workspace.getChildAt(0), childRect);
787360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
788360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            int page = workspace.getNextPage();
789f499b916e64ac776c7c57199985e0ec841141eecJohn Spurlock            final boolean isRtl = isLayoutDirectionRtl();
790fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung            CellLayout leftPage = (CellLayout) workspace.getChildAt(isRtl ? page + 1 : page - 1);
791fe1fe268b6d9ffd99218117795b3524a87e5110bWinson Chung            CellLayout rightPage = (CellLayout) workspace.getChildAt(isRtl ? page - 1 : page + 1);
792360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung
793360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            if (leftPage != null && leftPage.getIsDragOverlapping()) {
794360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mLeftHoverDrawable.setBounds(0, childRect.top,
795360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                        mLeftHoverDrawable.getIntrinsicWidth(), childRect.bottom);
796360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mLeftHoverDrawable.draw(canvas);
797360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            } else if (rightPage != null && rightPage.getIsDragOverlapping()) {
798360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mRightHoverDrawable.setBounds(width - mRightHoverDrawable.getIntrinsicWidth(),
799360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                        childRect.top, width, childRect.bottom);
800360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung                mRightHoverDrawable.draw(canvas);
801360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung            }
802360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung        }
803360e63fd3e77247002b86da2a77bd8dfe8c8a807Winson Chung    }
80431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
805