DragLayer.java revision 6788269814a678af976dfc7d6135993e172ce586
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
196788269814a678af976dfc7d6135993e172ce586Adam Cohenimport java.util.ArrayList;
20d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
2131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
22120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohenimport android.graphics.Bitmap;
236788269814a678af976dfc7d6135993e172ce586Adam Cohenimport android.graphics.Rect;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
2531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.KeyEvent;
260e26059548e429e5d1c973bebe4c561bead2926fMichael Jurkaimport android.view.MotionEvent;
27ea3763c2672f77539538af8cdd395ad97058eaabRomain Guyimport android.view.View;
2831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout;
29120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohenimport android.widget.ImageView;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
316788269814a678af976dfc7d6135993e172ce586Adam Cohenimport com.android.launcher.R;
326788269814a678af976dfc7d6135993e172ce586Adam Cohen
3331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
340e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka * A ViewGroup that coordinates dragging across its descendants
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
3600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratopublic class DragLayer extends FrameLayout {
37120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private DragController mDragController;
38120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    private int[] mTmpXY = new int[2];
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
406788269814a678af976dfc7d6135993e172ce586Adam Cohen    // Variables relating to resizing widgets
416788269814a678af976dfc7d6135993e172ce586Adam Cohen    private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
426788269814a678af976dfc7d6135993e172ce586Adam Cohen            new ArrayList<AppWidgetResizeFrame>();
436788269814a678af976dfc7d6135993e172ce586Adam Cohen    private AppWidgetResizeFrame mCurrentResizeFrame;
446788269814a678af976dfc7d6135993e172ce586Adam Cohen    private int mXDown, mYDown;
456788269814a678af976dfc7d6135993e172ce586Adam Cohen
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
500e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
5231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
54be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung
55be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        // Disable multitouch across the workspace/all apps/customize tray
56be62afa34d58edab0fc9ba7499f0dd543039c903Winson Chung        setMotionEventSplittingEnabled(false);
5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
5831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController controller) {
6000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = controller;
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
6200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
6431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
6500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
6731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
686788269814a678af976dfc7d6135993e172ce586Adam Cohen    private boolean handleTouchDown(MotionEvent ev) {
696788269814a678af976dfc7d6135993e172ce586Adam Cohen        Rect hitRect = new Rect();
706788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
716788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
726788269814a678af976dfc7d6135993e172ce586Adam Cohen
736788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (AppWidgetResizeFrame child: mResizeFrames) {
746788269814a678af976dfc7d6135993e172ce586Adam Cohen            child.getHitRect(hitRect);
756788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (hitRect.contains(x, y)) {
766788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (child.beginResizeIfPointInRegion(x - child.getLeft(), y - child.getTop())) {
776788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = child;
786788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mXDown = x;
796788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mYDown = y;
806788269814a678af976dfc7d6135993e172ce586Adam Cohen                    requestDisallowInterceptTouchEvent(true);
816788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
826788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
836788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
846788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
856788269814a678af976dfc7d6135993e172ce586Adam Cohen        return false;
866788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
876788269814a678af976dfc7d6135993e172ce586Adam Cohen
8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
906788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
916788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (handleTouchDown(ev)) {
926788269814a678af976dfc7d6135993e172ce586Adam Cohen                return true;
93d1837cc69eb222371afdd30890f7215d117510f2Patrick Dubroy            }
941b607ed454ed22c2fd855cb3e428376520fb2388Adam Cohen        }
956788269814a678af976dfc7d6135993e172ce586Adam Cohen        clearAllResizeFrames();
964db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onInterceptTouchEvent(ev);
9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
1016788269814a678af976dfc7d6135993e172ce586Adam Cohen        boolean handled = false;
1026788269814a678af976dfc7d6135993e172ce586Adam Cohen        int action = ev.getAction();
1036788269814a678af976dfc7d6135993e172ce586Adam Cohen
1046788269814a678af976dfc7d6135993e172ce586Adam Cohen        int x = (int) ev.getX();
1056788269814a678af976dfc7d6135993e172ce586Adam Cohen        int y = (int) ev.getY();
1066788269814a678af976dfc7d6135993e172ce586Adam Cohen
1076788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
1086788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (ev.getAction() == MotionEvent.ACTION_DOWN) {
1096788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (handleTouchDown(ev)) {
1106788269814a678af976dfc7d6135993e172ce586Adam Cohen                    return true;
1116788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
1126788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
1136788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1146788269814a678af976dfc7d6135993e172ce586Adam Cohen
1156788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mCurrentResizeFrame != null) {
1166788269814a678af976dfc7d6135993e172ce586Adam Cohen            handled = true;
1176788269814a678af976dfc7d6135993e172ce586Adam Cohen            switch (action) {
1186788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_MOVE:
1196788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame.visualizeResizeForDelta(x - mXDown, y - mYDown);
1206788269814a678af976dfc7d6135993e172ce586Adam Cohen                    break;
1216788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_CANCEL:
1226788269814a678af976dfc7d6135993e172ce586Adam Cohen                case MotionEvent.ACTION_UP:
1236788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame.commitResizeForDelta(x - mXDown, y - mYDown);
1246788269814a678af976dfc7d6135993e172ce586Adam Cohen                    mCurrentResizeFrame = null;
1256788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
1266788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1276788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (handled) return true;
1284db52312c10e822162a21c60404f06f6e507f0d6Joe Onorato        return mDragController.onTouchEvent(ev);
12991a9c9636f10f1e12cd1f660b2e330634fbdc7dcRomain Guy    }
130ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
131ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @Override
132ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
133ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mDragController.dispatchUnhandledMove(focused, direction);
134ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
135120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
136120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    public View createDragView(Bitmap b, int xPos, int yPos) {
137120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        ImageView imageView = new ImageView(mContext);
138120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        imageView.setImageBitmap(b);
139120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        imageView.setX(xPos);
140120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        imageView.setY(yPos);
141120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        addView(imageView, b.getWidth(), b.getHeight());
142120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
143120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        return imageView;
144120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    }
145120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen
146120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    public View createDragView(View v) {
147120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        v.getLocationOnScreen(mTmpXY);
148120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
149120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    }
1506788269814a678af976dfc7d6135993e172ce586Adam Cohen
1516788269814a678af976dfc7d6135993e172ce586Adam Cohen    public static class LayoutParams extends FrameLayout.LayoutParams {
1526788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int x, y;
1536788269814a678af976dfc7d6135993e172ce586Adam Cohen        public boolean customPosition = false;
1546788269814a678af976dfc7d6135993e172ce586Adam Cohen
1556788269814a678af976dfc7d6135993e172ce586Adam Cohen        /**
1566788269814a678af976dfc7d6135993e172ce586Adam Cohen         * {@inheritDoc}
1576788269814a678af976dfc7d6135993e172ce586Adam Cohen         */
1586788269814a678af976dfc7d6135993e172ce586Adam Cohen        public LayoutParams(int width, int height) {
1596788269814a678af976dfc7d6135993e172ce586Adam Cohen            super(width, height);
1606788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1616788269814a678af976dfc7d6135993e172ce586Adam Cohen
1626788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setWidth(int width) {
1636788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.width = width;
1646788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1656788269814a678af976dfc7d6135993e172ce586Adam Cohen
1666788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getWidth() {
1676788269814a678af976dfc7d6135993e172ce586Adam Cohen            return width;
1686788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1696788269814a678af976dfc7d6135993e172ce586Adam Cohen
1706788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setHeight(int height) {
1716788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.height = height;
1726788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1736788269814a678af976dfc7d6135993e172ce586Adam Cohen
1746788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getHeight() {
1756788269814a678af976dfc7d6135993e172ce586Adam Cohen            return height;
1766788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1776788269814a678af976dfc7d6135993e172ce586Adam Cohen
1786788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setX(int x) {
1796788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.x = x;
1806788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1816788269814a678af976dfc7d6135993e172ce586Adam Cohen
1826788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getX() {
1836788269814a678af976dfc7d6135993e172ce586Adam Cohen            return x;
1846788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1856788269814a678af976dfc7d6135993e172ce586Adam Cohen
1866788269814a678af976dfc7d6135993e172ce586Adam Cohen        public void setY(int y) {
1876788269814a678af976dfc7d6135993e172ce586Adam Cohen            this.y = y;
1886788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1896788269814a678af976dfc7d6135993e172ce586Adam Cohen
1906788269814a678af976dfc7d6135993e172ce586Adam Cohen        public int getY() {
1916788269814a678af976dfc7d6135993e172ce586Adam Cohen            return y;
1926788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
1936788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
1946788269814a678af976dfc7d6135993e172ce586Adam Cohen
1956788269814a678af976dfc7d6135993e172ce586Adam Cohen    protected void onLayout(boolean changed, int l, int t, int r, int b) {
1966788269814a678af976dfc7d6135993e172ce586Adam Cohen        super.onLayout(changed, l, t, r, b);
1976788269814a678af976dfc7d6135993e172ce586Adam Cohen        int count = getChildCount();
1986788269814a678af976dfc7d6135993e172ce586Adam Cohen        for (int i = 0; i < count; i++) {
1996788269814a678af976dfc7d6135993e172ce586Adam Cohen            View child = getChildAt(i);
2006788269814a678af976dfc7d6135993e172ce586Adam Cohen            final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
2016788269814a678af976dfc7d6135993e172ce586Adam Cohen            if (flp instanceof LayoutParams) {
2026788269814a678af976dfc7d6135993e172ce586Adam Cohen                final LayoutParams lp = (LayoutParams) flp;
2036788269814a678af976dfc7d6135993e172ce586Adam Cohen                if (lp.customPosition) {
2046788269814a678af976dfc7d6135993e172ce586Adam Cohen                    child.layout(lp.x, lp.y, lp.x + lp.width, lp.y + lp.height);
2056788269814a678af976dfc7d6135993e172ce586Adam Cohen                }
2066788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2076788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2086788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
2096788269814a678af976dfc7d6135993e172ce586Adam Cohen
2106788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void clearAllResizeFrames() {
2116788269814a678af976dfc7d6135993e172ce586Adam Cohen        if (mResizeFrames.size() > 0) {
2126788269814a678af976dfc7d6135993e172ce586Adam Cohen            for (AppWidgetResizeFrame frame: mResizeFrames) {
2136788269814a678af976dfc7d6135993e172ce586Adam Cohen                removeView(frame);
2146788269814a678af976dfc7d6135993e172ce586Adam Cohen            }
2156788269814a678af976dfc7d6135993e172ce586Adam Cohen            mResizeFrames.clear();
2166788269814a678af976dfc7d6135993e172ce586Adam Cohen        }
2176788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
2186788269814a678af976dfc7d6135993e172ce586Adam Cohen
2196788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean hasResizeFrames() {
2206788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mResizeFrames.size() > 0;
2216788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
2226788269814a678af976dfc7d6135993e172ce586Adam Cohen
2236788269814a678af976dfc7d6135993e172ce586Adam Cohen    public boolean isWidgetBeingResized() {
2246788269814a678af976dfc7d6135993e172ce586Adam Cohen        return mCurrentResizeFrame != null;
2256788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
2266788269814a678af976dfc7d6135993e172ce586Adam Cohen
2276788269814a678af976dfc7d6135993e172ce586Adam Cohen    public void addResizeFrame(ItemInfo itemInfo, LauncherAppWidgetHostView widget,
2286788269814a678af976dfc7d6135993e172ce586Adam Cohen            CellLayout cellLayout) {
2296788269814a678af976dfc7d6135993e172ce586Adam Cohen        AppWidgetResizeFrame resizeFrame = new AppWidgetResizeFrame(getContext(),
2306788269814a678af976dfc7d6135993e172ce586Adam Cohen                itemInfo, widget, cellLayout, this);
2316788269814a678af976dfc7d6135993e172ce586Adam Cohen
2326788269814a678af976dfc7d6135993e172ce586Adam Cohen        LayoutParams lp = new LayoutParams(-1, -1);
2336788269814a678af976dfc7d6135993e172ce586Adam Cohen        lp.customPosition = true;
2346788269814a678af976dfc7d6135993e172ce586Adam Cohen
2356788269814a678af976dfc7d6135993e172ce586Adam Cohen        addView(resizeFrame, lp);
2366788269814a678af976dfc7d6135993e172ce586Adam Cohen        mResizeFrames.add(resizeFrame);
2376788269814a678af976dfc7d6135993e172ce586Adam Cohen
2386788269814a678af976dfc7d6135993e172ce586Adam Cohen        resizeFrame.snapToWidget(false);
2396788269814a678af976dfc7d6135993e172ce586Adam Cohen    }
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
241