Workspace.java revision 678862186af4ea70d9b4012c9bc127e7fea5e607
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
190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.app.WallpaperManager;
208edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurkaimport android.content.Context;
21b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.content.Intent;
220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.content.ComponentName;
23cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.content.res.TypedArray;
24cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.content.pm.PackageManager;
25716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohenimport android.graphics.Canvas;
26cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.graphics.RectF;
2768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport android.graphics.Rect;
288f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.graphics.drawable.Drawable;
29629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.util.AttributeSet;
30629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.view.MotionEvent;
31a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.VelocityTracker;
32a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.View;
33495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.view.ViewConfiguration;
3431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.ViewGroup;
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.ViewParent;
36495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.widget.Scroller;
377247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.widget.TextView;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Parcelable;
394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.os.Parcel;
406b879f0a5885274a85333531e091283405d490ccAdam Lesinski
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.ArrayList;
42a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
43a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung/**
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * The workspace is a wide area with a wallpaper and a finite number of screens. Each
45a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung * screen contains a number of icons, folders or widgets the user can interact with.
464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato * A workspace is meant to be used with a fixed width only.
47f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project */
48956091ba7863bd72086275e61084864994dd6fa7Joe Onoratopublic class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller {
49495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell    private static final int INVALID_SCREEN = -1;
5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
51b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung    /**
52291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler     * The velocity at which a fling gesture will cause us to snap to the next screen
53580e27748137ff08599aa719d106b31215a28353Winson Chung     */
54a34abf8c781485b788fddacb352d586bffca886cWinson Chung    private static final int SNAP_VELOCITY = 1000;
55a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final WallpaperManager mWallpaperManager;
5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
586e3140865d3f0def2e55934d8b0b2c1503386e54Winson Chung    private int mDefaultScreen;
59cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
60f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    private boolean mFirstLayout = true;
61a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
6231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mCurrentScreen;
636639687cd67bab1aeef2a75e5c6bc458b20dc082Adam Cohen    private int mNextScreen = INVALID_SCREEN;
6419072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen    private Scroller mScroller;
656639687cd67bab1aeef2a75e5c6bc458b20dc082Adam Cohen    private VelocityTracker mVelocityTracker;
66edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
67716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    /**
68716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen     * CellInfo for the cell that is currently being dragged
69716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen     */
70716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    private CellLayout.CellInfo mDragInfo;
7131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    /**
730142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * Target drop area calculated during last acceptDrop call.
74aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     */
7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTargetCell = null;
760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
77e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    private float mLastMotionX;
78e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    private float mLastMotionY;
79e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy
803a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private final static int TOUCH_STATE_REST = 0;
810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private final static int TOUCH_STATE_SCROLLING = 1;
82f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
83f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private int mTouchState = TOUCH_STATE_REST;
84a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
85a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private OnLongClickListener mLongClickListener;
86a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
871b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private Launcher mLauncher;
88a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private DragController mDragController;
891b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
90a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    /**
9168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen     * Cache of vacant cells, used during drag events and invalidated as needed.
9268d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen     */
939171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private CellLayout.CellInfo mVacantCache = null;
94f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
95f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung    private int[] mTempCell = new int[2];
969171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private int[] mTempEstimate = new int[2];
979171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
989171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private boolean mAllowLongPress = true;
999171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
1009171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private int mTouchSlop;
1019171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private int mMaximumVelocity;
1029171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
1039171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    final Rect mDrawerBounds = new Rect();
104e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka    final Rect mClipBounds = new Rect();
105e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka    int mDrawerContentHeight;
1069171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    int mDrawerContentWidth;
10725356e75ebae5d6e0be43f38d2c73b5cb59d05f2Michael Jurka
108f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    /**
10968d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen     * Used to inflate the Workspace from XML.
110e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen     *
111f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen     * @param context The application's context.
112f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung     * @param attrs The attribtues set containing the Workspace's customization values.
11388127038178b3bbf0eb91103a31e682cc0615074Winson Chung     */
1148f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    public Workspace(Context context, AttributeSet attrs) {
1159c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        this(context, attrs, 0);
116aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
1170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
119d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka     * Used to inflate the Workspace from XML.
120e0310965022e7a1adb7ad489505d404186608689Adam Cohen     *
12121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen     * @param context The application's context.
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param attrs The attribtues set containing the Workspace's customization values.
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
126aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        super(context, attrs, defStyle);
12770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
12870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        mWallpaperManager = WallpaperManager.getInstance(context);
12970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
130c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Workspace, defStyle, 0);
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDefaultScreen = a.getInt(R.styleable.Workspace_defaultScreen, 1);
1326569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        a.recycle();
1336569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1346569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        initWorkspace();
1356569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    }
1366569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
1380589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato     * Initializes various states for this workspace.
13900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
140aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void initWorkspace() {
1414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mScroller = new Scroller(getContext());
1424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mCurrentScreen = mDefaultScreen;
14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        Launcher.setScreen(mCurrentScreen);
14470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
145e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
146a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        mTouchSlop = configuration.getScaledTouchSlop();
1474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
1484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    }
149a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
150c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen    @Override
1510280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public void addView(View child, int index, LayoutParams params) {
152073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen        if (!(child instanceof CellLayout)) {
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
154c2f7f4794867cd1b3e97fd0f379ad8ad15958a6cMichael Jurka        }
155b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung        super.addView(child, index, params);
156d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka    }
157d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen
158d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    @Override
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
1601262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!(child instanceof CellLayout)) {
161dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
162c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        }
163c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        super.addView(child);
164bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka    }
165b8e14479da7209ca811a753b3256fe4a0b49a873Michael Jurka
166f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    @Override
167af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka    public void addView(View child, int index) {
168883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (!(child instanceof CellLayout)) {
169af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
1703c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        }
171dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        super.addView(child, index);
17254fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy    }
1731262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1741262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
17554fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy    public void addView(View child, int width, int height) {
17654fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy        if (!(child instanceof CellLayout)) {
17754fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
1788e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        }
1794be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        super.addView(child, width, height);
1808e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    }
1818e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy
1824be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    @Override
183a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    public void addView(View child, LayoutParams params) {
184a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        if (!(child instanceof CellLayout)) {
185a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
1866b879f0a5885274a85333531e091283405d490ccAdam Lesinski        }
1876b879f0a5885274a85333531e091283405d490ccAdam Lesinski        super.addView(child, params);
1886b879f0a5885274a85333531e091283405d490ccAdam Lesinski    }
1896b879f0a5885274a85333531e091283405d490ccAdam Lesinski
1906b879f0a5885274a85333531e091283405d490ccAdam Lesinski    /**
191c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka     * @return The open folder on the current screen, or null if there is none
192c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka     */
193c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    Folder getOpenFolder() {
194ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen);
195c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        int count = currentScreen.getChildCount();
196ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        for (int i = 0; i < count; i++) {
19726976d9b53161f80faf822d482ac771b8621cf31Adam Cohen            View child = currentScreen.getChildAt(i);
198c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
1990bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka            if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
2000bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka                return (Folder) child;
2010bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka            }
2020bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka        }
2030bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka        return null;
2040bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka    }
2050bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka
20619072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen    ArrayList<Folder> getOpenFolders() {
207c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen        final int screens = getChildCount();
20819072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen        ArrayList<Folder> folders = new ArrayList<Folder>(screens);
20919072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen
21019072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen        for (int screen = 0; screen < screens; screen++) {
21119072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen            CellLayout currentScreen = (CellLayout) getChildAt(screen);
21219072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen            int count = currentScreen.getChildCount();
21319072da7441e07d5e90026d9e9e1b38f11245e44Adam Cohen            for (int i = 0; i < count; i++) {
214073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen                View child = currentScreen.getChildAt(i);
215f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
216f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
217f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen                    folders.add((Folder) child);
218f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen                    break;
219f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen                }
220f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            }
221f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        }
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultScreenShowing() {
22731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return mCurrentScreen == mDefaultScreen;
22831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Returns the index of the currently displayed screen.
23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The index of the currently displayed screen.
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    int getCurrentScreen() {
2360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentScreen;
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Returns how many screens there are.
2410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     */
2425f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    int getScreenCount() {
243f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return getChildCount();
244f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    }
245f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
246a2eb17095dcffa75c1e9681fdc318fe6e0564321Michael Jurka    /**
2475f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka     * Computes a bounding rectangle for a range of cells
2485f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka     *
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param cellX X coordinate of upper left corner expressed as a cell position
2508f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn     * @param cellY Y coordinate of upper left corner expressed as a cell position
251aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     * @param cellHSpan Width in cells
252f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka     * @param cellVSpan Height in cells
253f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka     * @param rect Rectnagle into which to put the results
254f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka     */
255aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF rect) {
256aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        ((CellLayout)getChildAt(mCurrentScreen)).cellToRect(cellX, cellY,
257f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka                cellHSpan, cellVSpan, rect);
258b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung    }
259f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka
260f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka    /**
261f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka     * Sets the current screen.
262f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka     *
263f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka     * @param currentScreen
264b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung     */
265b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung    void setCurrentScreen(int currentScreen) {
266b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung        clearVacantCache();
267f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka        mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
268f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka        scrollTo(mCurrentScreen * getWidth(), 0);
269f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka        updateWallpaperOffset();
270f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka        invalidate();
271f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka    }
272f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka
273f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka    /**
274f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka     * Shows the default screen (defined by the firstScreen attribute in XML.)
275f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka     */
276f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka    void showDefaultScreen() {
277f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka        setCurrentScreen(mDefaultScreen);
278f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka    }
279f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka
280f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka    /**
281f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka     * Adds the specified child in the current screen. The position and dimension of
282f61249b79948a4b37b38104cbe81c98086d1f30bMichael Jurka     * the child are defined by x, y, spanX and spanY.
283f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka     *
284f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka     * @param child The child to add in one of the workspace's screens.
285f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka     * @param x The X position of the child in the screen's grid.
286b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung     * @param y The Y position of the child in the screen's grid.
287b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung     * @param spanX The number of cells spanned horizontally by the child.
288b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung     * @param spanY The number of cells spanned vertically by the child.
289f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka     */
290f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka    void addInCurrentScreen(View child, int x, int y, int spanX, int spanY) {
291f6440da9d02f3ee1553db4bd431a202eb1d1a9ddMichael Jurka        addInScreen(child, mCurrentScreen, x, y, spanX, spanY, false);
2920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
295d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen     * Adds the specified child in the current screen. The position and dimension of
2960d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato     * the child are defined by x, y, spanX and spanY.
2970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     *
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
299c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung     * @param x The X position of the child in the screen's grid.
300c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung     * @param y The Y position of the child in the screen's grid.
301c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung     * @param spanX The number of cells spanned horizontally by the child.
30231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInCurrentScreen(View child, int x, int y, int spanX, int spanY, boolean insert) {
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, mCurrentScreen, x, y, spanX, spanY, insert);
3070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
3080589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
3090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    /**
3100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * Adds the specified child in the specified screen. The position and dimension of
3110589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato     * the child are defined by x, y, spanX and spanY.
3120589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato     *
313a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * @param child The child to add in one of the workspace's screens.
314cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy     * @param screen The screen in which to add the child.
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
316b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung     * @param y The Y position of the child in the screen's grid.
317b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung     * @param spanX The number of cells spanned horizontally by the child.
318fd3385fe9e0f034b04f99d5d59a58d74fe040da4Winson Chung     * @param spanY The number of cells spanned vertically by the child.
319b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung     */
320b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
321b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung        addInScreen(child, screen, x, y, spanX, spanY, false);
3229171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    }
3238edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka
3243c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka    /**
325c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka     * Adds the specified child in the specified screen. The position and dimension of
326c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka     * the child are defined by x, y, spanX and spanY.
327c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka     *
3280bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka     * @param child The child to add in one of the workspace's screens.
3293c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka     * @param screen The screen in which to add the child.
3308edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka     * @param x The X position of the child in the screen's grid.
331c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka     * @param y The Y position of the child in the screen's grid.
332ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka     * @param spanX The number of cells spanned horizontally by the child.
333f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung     * @param spanY The number of cells spanned vertically by the child.
334f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung     * @param insert When true, the child is inserted at the beginning of the children list.
335f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung     */
336f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
337f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        if (screen < 0 || screen >= getChildCount()) {
338f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung            throw new IllegalStateException("The screen must be >= 0 and < " + getChildCount());
339a58f8bb1947af39d4d18d849b3e4d6bd0d3954d7Winson Chung        }
340ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
34160b7c53ccc6384b65aaca77d97794e8f09e8cfc8Patrick Dubroy        clearVacantCache();
342ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka
343bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka        final CellLayout group = (CellLayout) getChildAt(screen);
344bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
345bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka        if (lp == null) {
346bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
347ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        } else {
348ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            lp.cellX = x;
349ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            lp.cellY = y;
350ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            lp.cellHSpan = spanX;
351bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka            lp.cellVSpan = spanY;
352ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        }
35360b7c53ccc6384b65aaca77d97794e8f09e8cfc8Patrick Dubroy        group.addView(child, insert ? 0 : -1, lp);
354dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        if (!(child instanceof Folder)) {
355dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            child.setOnLongClickListener(mLongClickListener);
3560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
357ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        if (child instanceof DropTarget) {
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mDragController.addDropTarget((DropTarget)child);
35931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
36031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
361f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
362b26f3d6a8c62e7c1a603b6c7979375d8dd4f20d4Winson Chung    void addWidget(View view, Widget widget) {
363f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        addInScreen(view, widget.screen, widget.cellX, widget.cellY, widget.spanX,
364f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                widget.spanY, false);
365e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka    }
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addWidget(View view, Widget widget, boolean insert) {
36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(view, widget.screen, widget.cellX, widget.cellY, widget.spanX,
3692801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                widget.spanY, insert);
3702801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
3712801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
3722801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    CellLayout.CellInfo findAllVacantCells(boolean[] occupied) {
3732801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        CellLayout group = (CellLayout) getChildAt(mCurrentScreen);
374e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka        if (group != null) {
3752801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            return group.findAllVacantCells(occupied, null);
376e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka        }
377e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka        return null;
378e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka    }
37931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private void clearVacantCache() {
38131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (mVacantCache != null) {
38231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mVacantCache.clearVacantCells();
38331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mVacantCache = null;
384e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka        }
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Returns the coordinate of a vacant cell for the current screen.
38931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
390e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka    boolean getVacantCell(int[] vacant, int spanX, int spanY) {
39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout group = (CellLayout) getChildAt(mCurrentScreen);
39231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (group != null) {
39331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return group.getVacantCell(vacant, spanX, spanY);
39431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
39531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
396e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka    }
39731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
39831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
39931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the current screen. The position and dimension of
40031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
40131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
402e5fb0f27bca7afb996258a7163c76ca7390d7bffMichael Jurka     * @param child The child to add in one of the workspace's screens.
40331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
40431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
40531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
40631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void fitInCurrentScreen(View child, int spanX, int spanY) {
40731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        fitInScreen(child, mCurrentScreen, spanX, spanY);
40831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
40931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
410716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen    /**
4118e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen     * Adds the specified child in the specified screen. The position and dimension of
41231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
4138e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen     *
414aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     * @param child The child to add in one of the workspace's screens.
415aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     * @param screen The screen in which to add the child.
416aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     * @param spanX The number of cells spanned horizontally by the child.
417aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     * @param spanY The number of cells spanned vertically by the child.
41831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
41931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void fitInScreen(View child, int screen, int spanX, int spanY) {
42031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
42131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalStateException("The screen must be >= 0 and < " + getChildCount());
42231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
423a0aa0121b91fde17e427ab2763ce312e64cf5d33Patrick Dubroy
424a0aa0121b91fde17e427ab2763ce312e64cf5d33Patrick Dubroy        final CellLayout group = (CellLayout) getChildAt(screen);
42531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        boolean vacant = group.getVacantCell(mTempCell, spanX, spanY);
42631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (vacant) {
42731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            group.addView(child,
42831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    new CellLayout.LayoutParams(mTempCell[0], mTempCell[1], spanX, spanY));
42931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
43031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (!(child instanceof Folder)) {
43131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                child.setOnLongClickListener(mLongClickListener);
43231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
43331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (child instanceof DropTarget) {
43431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mDragController.addDropTarget((DropTarget)child);
43531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
43631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
43731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
43831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
44031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Registers the specified listener on each screen contained in this workspace.
44131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
442aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     * @param l The listener used to respond to long clicks.
443aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     */
444aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    @Override
445aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void setOnLongClickListener(OnLongClickListener l) {
44631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLongClickListener = l;
44731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int count = getChildCount();
44831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
44931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            getChildAt(i).setOnLongClickListener(l);
45031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
45131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
45231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
45331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private void updateWallpaperOffset() {
45431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
45531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
45631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
45731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private void updateWallpaperOffset(int scrollRange) {
45831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mWallpaperManager.setWallpaperOffsets(getWindowToken(), mScrollX / (float) scrollRange, 0);
45931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
460291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler
461291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler    @Override
462291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler    public void computeScroll() {
46331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (mScroller.computeScrollOffset()) {
46431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mScrollX = mScroller.getCurrX();
46531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mScrollY = mScroller.getCurrY();
46631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            updateWallpaperOffset();
46731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            postInvalidate();
46831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else if (mNextScreen != INVALID_SCREEN) {
46931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
47031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            Launcher.setScreen(mCurrentScreen);
47131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mNextScreen = INVALID_SCREEN;
47231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            clearChildrenCache();
47331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
47431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
475aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
4767f4eabe3709a72b416569136e4a095431c493c8bAdam Cohen    @Override
4777f4eabe3709a72b416569136e4a095431c493c8bAdam Cohen    protected void dispatchDraw(Canvas canvas) {
4787f4eabe3709a72b416569136e4a095431c493c8bAdam Cohen        boolean restore = false;
4797f4eabe3709a72b416569136e4a095431c493c8bAdam Cohen        int restoreCount = 0;
4806569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
481845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        // For the fade.  If view gets setAlpha(), use that instead.
482f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        float scale = mScale;
483f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        if (scale < 0.999f) {
484aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int sx = mScrollX;
485aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
4866569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            int alpha = (scale < 0.5f) ? (int)(255 * 2 * scale) : 255;
487aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
488aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            restoreCount = canvas.saveLayerAlpha(sx, 0, sx+getWidth(), getHeight(), alpha,
489aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
49031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            restore = true;
4910d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato
49231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (scale < 0.999f) {
49331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                int w = getWidth();
49400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                w += 2 * mCurrentScreen * w;
495aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                int dx = w/2;
49600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                int h = getHeight();
49731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                int dy = (h/2) - (h/4);
49831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                canvas.translate(dx, dy);
499d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                canvas.scale(scale, scale);
500d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                canvas.translate(-dx, -dy);
501d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            }
502d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        }
503d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy
504d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        // ViewGroup.dispatchDraw() supports many features we don't need:
505d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        // clip to padding, layout animation, animation listener, disappearing
506d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        // children, etc. The following implementation attempts to fast-track
507d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        // the drawing dispatch by drawing only what we know needs to be drawn.
508d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy
509d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN
510d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                && scale > 0.999f;
511d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        // If we are not scrolling or flinging, draw only the current screen
512d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        if (fastDraw) {
513d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());
514d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        } else {
515d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            final long drawingTime = getDrawingTime();
516d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            // If we are flinging, draw only the current screen and the target screen
517d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            if (mNextScreen >= 0 && mNextScreen < getChildCount() &&
518d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                    Math.abs(mCurrentScreen - mNextScreen) == 1) {
519d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                drawChild(canvas, getChildAt(mCurrentScreen), drawingTime);
520d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                drawChild(canvas, getChildAt(mNextScreen), drawingTime);
521d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            } else {
522d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                // If we are scrolling, draw all of our children
523d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                final int count = getChildCount();
524d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                for (int i = 0; i < count; i++) {
525d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                    drawChild(canvas, getChildAt(i), drawingTime);
526d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy                }
527d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            }
528d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        }
529e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
530e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        if (restore) {
531e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy            canvas.restoreToCount(restoreCount);
532e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        }
533e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    }
534e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
535dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private float mScale = 1.0f;
536e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    public void setScale(float scale) {
537e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        mScale = scale;
538e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        invalidate();
539e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    }
540e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
541e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    protected void onAttachedToWindow() {
542e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        super.onAttachedToWindow();
543e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        mDragController.setWindowToken(getWindowToken());
544e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    }
545e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
546e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    @Override
547dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
5480e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
5490e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
550ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen        final int width = MeasureSpec.getSize(widthMeasureSpec);
551ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
552ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen        if (widthMode != MeasureSpec.EXACTLY) {
553ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
5545f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
5555f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
556c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
5575f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (heightMode != MeasureSpec.EXACTLY) {
5585f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
5595f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
5605f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
5615f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // The children are given the same width and height as the workspace
5625f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        final int count = getChildCount();
5635f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        for (int i = 0; i < count; i++) {
5645f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
565f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        }
566f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen
567f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        if (mFirstLayout) {
568f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            scrollTo(mCurrentScreen * width, 0);
569f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            updateWallpaperOffset(width * (getChildCount() - 1));
5705f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFirstLayout = false;
5715f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
5725f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
5731adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka
5741adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    @Override
57569c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
57669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        int childLeft = 0;
57769c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen
578f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        final int count = getChildCount();
57969c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        for (int i = 0; i < count; i++) {
580f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            final View child = getChildAt(i);
58169c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            if (child.getVisibility() != View.GONE) {
58269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen                final int childWidth = child.getMeasuredWidth();
583f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen                child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
58469c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen                childLeft += childWidth;
58569c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            }
58669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        }
587f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen    }
58869c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen
58969c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen    @Override
59069c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
59169c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        int screen = indexOfChild(child);
59269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        if (screen != mCurrentScreen || !mScroller.isFinished()) {
59369c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            if (!mLauncher.isWorkspaceLocked()) {
59469c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen                snapToScreen(screen);
59569c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            }
59669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            return true;
59769c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        }
59869c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        return false;
59969c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen    }
60069c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen
60169c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen    @Override
60269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
60369c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        if (!mLauncher.isAllAppsVisible()) {
604f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            final Folder openFolder = getOpenFolder();
6051adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka            if (openFolder != null) {
6061adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka                return openFolder.requestFocus(direction, previouslyFocusedRect);
607007c69867d821ea2b271398577a8b3440b3a7046Winson Chung            } else {
608007c69867d821ea2b271398577a8b3440b3a7046Winson Chung                int focusableScreen;
609007c69867d821ea2b271398577a8b3440b3a7046Winson Chung                if (mNextScreen != INVALID_SCREEN) {
610007c69867d821ea2b271398577a8b3440b3a7046Winson Chung                    focusableScreen = mNextScreen;
611007c69867d821ea2b271398577a8b3440b3a7046Winson Chung                } else {
6121262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                    focusableScreen = mCurrentScreen;
613007c69867d821ea2b271398577a8b3440b3a7046Winson Chung                }
614007c69867d821ea2b271398577a8b3440b3a7046Winson Chung                getChildAt(focusableScreen).requestFocus(direction, previouslyFocusedRect);
6150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
6160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
61716fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        return false;
6180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
6190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
62116fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
62231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (direction == View.FOCUS_LEFT) {
623007c69867d821ea2b271398577a8b3440b3a7046Winson Chung            if (getCurrentScreen() > 0) {
624007c69867d821ea2b271398577a8b3440b3a7046Winson Chung                snapToScreen(getCurrentScreen() - 1);
625007c69867d821ea2b271398577a8b3440b3a7046Winson Chung                return true;
626007c69867d821ea2b271398577a8b3440b3a7046Winson Chung            }
627007c69867d821ea2b271398577a8b3440b3a7046Winson Chung        } else if (direction == View.FOCUS_RIGHT) {
62831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (getCurrentScreen() < getChildCount() - 1) {
62931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                snapToScreen(getCurrentScreen() + 1);
6301262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                return true;
631007c69867d821ea2b271398577a8b3440b3a7046Winson Chung            }
632007c69867d821ea2b271398577a8b3440b3a7046Winson Chung        }
63316fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        return super.dispatchUnhandledMove(focused, direction);
6341262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
6351262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
636007c69867d821ea2b271398577a8b3440b3a7046Winson Chung    @Override
637007c69867d821ea2b271398577a8b3440b3a7046Winson Chung    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
638007c69867d821ea2b271398577a8b3440b3a7046Winson Chung        if (!mLauncher.isAllAppsVisible()) {
639007c69867d821ea2b271398577a8b3440b3a7046Winson Chung            final Folder openFolder = getOpenFolder();
6401262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            if (openFolder == null) {
64168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                getChildAt(mCurrentScreen).addFocusables(views, direction);
642e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen                if (direction == View.FOCUS_LEFT) {
64326976d9b53161f80faf822d482ac771b8621cf31Adam Cohen                    if (mCurrentScreen > 0) {
64426976d9b53161f80faf822d482ac771b8621cf31Adam Cohen                        getChildAt(mCurrentScreen - 1).addFocusables(views, direction);
64526976d9b53161f80faf822d482ac771b8621cf31Adam Cohen                    }
64626976d9b53161f80faf822d482ac771b8621cf31Adam Cohen                } else if (direction == View.FOCUS_RIGHT){
64726976d9b53161f80faf822d482ac771b8621cf31Adam Cohen                    if (mCurrentScreen < getChildCount() - 1) {
6480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                        getChildAt(mCurrentScreen + 1).addFocusables(views, direction);
6490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                    }
6500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                }
6510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
6520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                openFolder.addFocusables(views, direction);
6530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
6540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
6550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
656c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
657c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    @Override
658c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
659c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) {
660c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            return false; // We don't want the events.  Let them fall through to the all apps view.
661c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        }
662c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
663c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        /*
664c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * This method JUST determines whether we want to intercept the motion.
665c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * If we return true, onTouchEvent will be called and we do the actual
666c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * scrolling there.
667c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         */
668c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
669c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        /*
670c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * Shortcut the most recurring case: the user is in the dragging
671c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * state and he is moving his finger.  We want to intercept this
672c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * motion.
673c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         */
674c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        final int action = ev.getAction();
675c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) {
676c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            return true;
677c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        }
678c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
679c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        final float x = ev.getX();
680c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        final float y = ev.getY();
681c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
682c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        switch (action) {
683c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            case MotionEvent.ACTION_MOVE:
684c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                /*
685c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
686c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                 * whether the user has moved far enough from his original down touch.
687c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                 */
688c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
689c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                /*
690c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                 * Locally do absolute value. mLastMotionX is set to the y value
691c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                 * of the down event.
692c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                 */
693c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                final int xDiff = (int) Math.abs(x - mLastMotionX);
694c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                final int yDiff = (int) Math.abs(y - mLastMotionY);
695c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
696201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung                final int touchSlop = mTouchSlop;
697201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung                boolean xMoved = xDiff > touchSlop;
698201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung                boolean yMoved = yDiff > touchSlop;
699201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung
700c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                if (xMoved || yMoved) {
701c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
702c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                    if (xMoved) {
703c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                        // Scroll if the user moved far enough along the X axis
704c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                        mTouchState = TOUCH_STATE_SCROLLING;
705f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung                        enableChildrenCache();
706f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung                    }
707f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung                    // Either way, cancel any pending longpress
708f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung                    if (mAllowLongPress) {
709f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung                        mAllowLongPress = false;
710c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                        // Try canceling the long press. It could also have been scheduled
711c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                        // by a distant descendant, so use the mAllowLongPress flag to block
712ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        // everything
713ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        final View currentScreen = getChildAt(mCurrentScreen);
714ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        currentScreen.cancelLongPress();
715ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    }
716ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                }
717ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                break;
718ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
719ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            case MotionEvent.ACTION_DOWN:
720ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                // Remember location of down touch
721ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mLastMotionX = x;
722ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mLastMotionY = y;
723c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                mAllowLongPress = true;
724c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
725ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                /*
726ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 * If being flinged and user touches the screen, initiate drag;
727f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka                 * otherwise don't.  mScroller.isFinished should be false when
728ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 * being flinged.
729ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 */
730ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
731ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                break;
732ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
733f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka            case MotionEvent.ACTION_CANCEL:
734f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka            case MotionEvent.ACTION_UP:
735f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka                // Release the drag
736ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                clearChildrenCache();
737ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mTouchState = TOUCH_STATE_REST;
738ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mAllowLongPress = false;
739ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                break;
740ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
741ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
74209d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        /*
74309d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka         * The only time we want to intercept motion events is if we are in the
74409d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka         * drag mode.
74509d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka         */
74609d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        return mTouchState != TOUCH_STATE_REST;
74709d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka    }
74809d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka
74909d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka    void enableChildrenCache() {
75009d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        final int count = getChildCount();
75109d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        for (int i = 0; i < count; i++) {
75209d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka            final CellLayout layout = (CellLayout) getChildAt(i);
75309d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka            layout.setChildrenDrawnWithCacheEnabled(true);
75409d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka            layout.setChildrenDrawingCacheEnabled(true);
755ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
75609d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka    }
757ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
758f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka    void clearChildrenCache() {
759ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final int count = getChildCount();
760ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        for (int i = 0; i < count; i++) {
761ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            final CellLayout layout = (CellLayout) getChildAt(i);
762ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            layout.setChildrenDrawnWithCacheEnabled(false);
763b46a2d130b3d04df830402d579060b63db559ae3Winson Chung        }
764b46a2d130b3d04df830402d579060b63db559ae3Winson Chung    }
765ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
766c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    @Override
767c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    public boolean onTouchEvent(MotionEvent ev) {
768c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
769c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) {
770c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            return false; // We don't want the events.  Let them fall through to the all apps view.
771c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        }
772c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
773ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        if (mVelocityTracker == null) {
774ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            mVelocityTracker = VelocityTracker.obtain();
775ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
776ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        mVelocityTracker.addMovement(ev);
777ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
778ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final int action = ev.getAction();
779ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final float x = ev.getX();
780ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
781c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        switch (action) {
782ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        case MotionEvent.ACTION_DOWN:
783ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            /*
784ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka             * If being flinged and user touches, stop the fling. isFinished
7859c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka             * will be false if being flinged.
7869c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka             */
787ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            if (!mScroller.isFinished()) {
788ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mScroller.abortAnimation();
789ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            }
790ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
7912763be3150d429d338b9848286e9365b4052c100Michael Jurka            // Remember where the motion event started
792956091ba7863bd72086275e61084864994dd6fa7Joe Onorato            mLastMotionX = x;
793ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            break;
794ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        case MotionEvent.ACTION_MOVE:
795ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            if (mTouchState == TOUCH_STATE_SCROLLING) {
796ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                // Scroll to follow the motion event
797ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                final int deltaX = (int) (mLastMotionX - x);
798ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mLastMotionX = x;
799ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
800ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                if (deltaX < 0) {
801ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    if (mScrollX > 0) {
802ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        scrollBy(Math.max(-mScrollX, deltaX), 0);
803ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        updateWallpaperOffset();
804ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    }
805ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                } else if (deltaX > 0) {
806ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    final int availableToScroll = getChildAt(getChildCount() - 1).getRight() -
807ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                            mScrollX - getWidth();
808ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    if (availableToScroll > 0) {
809ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        scrollBy(Math.min(availableToScroll, deltaX), 0);
810ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        updateWallpaperOffset();
811ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    }
812ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                }
813ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            }
814ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            break;
815ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        case MotionEvent.ACTION_UP:
816ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            if (mTouchState == TOUCH_STATE_SCROLLING) {
817ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                final VelocityTracker velocityTracker = mVelocityTracker;
818ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
819ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                int velocityX = (int) velocityTracker.getXVelocity();
820ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
821ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
822ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    // Fling hard enough to move left
823ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    snapToScreen(mCurrentScreen - 1);
824ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
825ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    // Fling hard enough to move right
826ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    snapToScreen(mCurrentScreen + 1);
827ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                } else {
828ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    snapToDestination();
829ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                }
830ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
831ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                if (mVelocityTracker != null) {
832ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    mVelocityTracker.recycle();
833ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    mVelocityTracker = null;
834ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                }
835ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            }
836ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            mTouchState = TOUCH_STATE_REST;
837ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            break;
838ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        case MotionEvent.ACTION_CANCEL:
839ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            mTouchState = TOUCH_STATE_REST;
840ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        }
841ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
842ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        return true;
843ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka    }
844ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
845ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka    private void snapToDestination() {
846ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        final int screenWidth = getWidth();
847ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
848ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
849ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        snapToScreen(whichScreen);
850ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka    }
851ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
852ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka    void snapToScreen(int whichScreen) {
853ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        if (!mScroller.isFinished()) return;
854ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
855ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        clearVacantCache();
856ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        enableChildrenCache();
857ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
858ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
859ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        boolean changingScreens = whichScreen != mCurrentScreen;
860ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
861ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        mNextScreen = whichScreen;
862ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
863ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        View focusedChild = getFocusedChild();
864ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        if (focusedChild != null && changingScreens && focusedChild == getChildAt(mCurrentScreen)) {
865ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            focusedChild.clearFocus();
866ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        }
867ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
868ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final int newX = whichScreen * getWidth();
869ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final int delta = newX - mScrollX;
870ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        mScroller.startScroll(mScrollX, 0, delta, 0, Math.abs(delta) * 2);
871ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        invalidate();
872ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    }
873ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
874ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    void startDrag(CellLayout.CellInfo cellInfo) {
875ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        View child = cellInfo.cell;
876ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
877ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        // Make sure the drag was started by a long press as opposed to a long click.
878ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        // Note that Search takes focus when clicked rather than entering touch mode
879ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        if (!child.isInTouchMode() && !(child instanceof Search)) {
880ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            return;
881ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
882ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
883ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        mDragInfo = cellInfo;
884ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        mDragInfo.screen = mCurrentScreen;
885ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
886ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        CellLayout current = ((CellLayout) getChildAt(mCurrentScreen));
887ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
888ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        current.onDragChild(child);
889ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
890ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        invalidate();
891ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    }
892ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
893ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    @Override
894ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    protected Parcelable onSaveInstanceState() {
895ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final SavedState state = new SavedState(super.onSaveInstanceState());
896ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        state.currentScreen = mCurrentScreen;
897ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        return state;
898ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    }
899ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
900ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    @Override
901ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    protected void onRestoreInstanceState(Parcelable state) {
902ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        SavedState savedState = (SavedState) state;
9038f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        super.onRestoreInstanceState(savedState.getSuperState());
904aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (savedState.currentScreen != -1) {
905340c5f3a708efa280a120708594247952ca65182Michael Jurka            mCurrentScreen = savedState.currentScreen;
906340c5f3a708efa280a120708594247952ca65182Michael Jurka            Launcher.setScreen(mCurrentScreen);
907340c5f3a708efa280a120708594247952ca65182Michael Jurka        }
908ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    }
909ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
910ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo) {
911340c5f3a708efa280a120708594247952ca65182Michael Jurka        addApplicationShortcut(info, cellInfo, false);
912340c5f3a708efa280a120708594247952ca65182Michael Jurka    }
91394f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy
9143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    void addApplicationShortcut(ApplicationInfo info, CellLayout.CellInfo cellInfo,
9159171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            boolean insertAtFirst) {
9169171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen);
9179171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        final int[] result = new int[2];
9189171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
9199171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        layout.cellToPoint(cellInfo.cellX, cellInfo.cellY, result);
9203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        onDropExternal(result[0], result[1], info, layout, insertAtFirst);
921f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
922f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
92394f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
9243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            DragView dragView, Object dragInfo) {
9259171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        final CellLayout cellLayout = getCurrentDropLayout();
9269171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        if (source != this) {
9279171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            onDropExternal(x - xOffset, y - yOffset, dragInfo, cellLayout);
9289171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        } else {
9299171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            // Move internally
9309171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            if (mDragInfo != null) {
9313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                final View cell = mDragInfo.cell;
932f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen;
933f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (index != mDragInfo.screen) {
93494f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy                    final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
93594f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy                    originalCellLayout.removeView(cell);
93694f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy                    cellLayout.addView(cell);
93794f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy                }
93894f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy                mTargetCell = estimateDropCell(x - xOffset, y - yOffset,
93994f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy                        mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout, mTargetCell);
9409171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                cellLayout.onDropChild(cell, mTargetCell);
9419171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
942f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                final ItemInfo info = (ItemInfo)cell.getTag();
943f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
944f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                LauncherModel.moveItemInDatabase(mLauncher, info,
945f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                        LauncherSettings.Favorites.CONTAINER_DESKTOP, index, lp.cellX, lp.cellY);
946f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            }
947f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
9489171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    }
9499171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
9509171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset,
9519171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            DragView dragView, Object dragInfo) {
9529c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        clearVacantCache();
9539c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka    }
9549c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka
9559c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
9569c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            DragView dragView, Object dragInfo) {
9579c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka    }
9589c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka
959760e5375f003accf04f789e90a919ed476d4c335Winson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset,
960760e5375f003accf04f789e90a919ed476d4c335Winson Chung            DragView dragView, Object dragInfo) {
9618d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung        clearVacantCache();
9628d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung    }
9638d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung
964b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung    private void onDropExternal(int x, int y, Object dragInfo, CellLayout cellLayout) {
9659171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        onDropExternal(x, y, dragInfo, cellLayout, false);
9669171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    }
967e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka
968e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka    private void onDropExternal(int x, int y, Object dragInfo, CellLayout cellLayout,
969e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            boolean insertAtFirst) {
970e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka        // Drag from somewhere else
971e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka        ItemInfo info = (ItemInfo) dragInfo;
972e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka
973f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung        View view;
9749171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
9759171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        switch (info.itemType) {
9769171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
9779171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
9788d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung            if (info.container == NO_ID) {
979b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung                // Came from all apps -- make a copy
9809171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                info = new ApplicationInfo((ApplicationInfo) info);
9819171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            }
982e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            view = mLauncher.createShortcut(R.layout.application, cellLayout,
983e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka                    (ApplicationInfo) info);
984e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            break;
985e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
986e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
987e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka                    (ViewGroup) getChildAt(mCurrentScreen), ((UserFolderInfo) info));
988f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung            break;
9899171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        default:
9909171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            throw new IllegalStateException("Unknown item type: " + info.itemType);
9919171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        }
9929171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
9939171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        cellLayout.addView(view, insertAtFirst ? 0 : -1);
9949c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        view.setOnLongClickListener(mLongClickListener);
9959c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        if (view instanceof DropTarget) {
9969c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            mDragController.addDropTarget((DropTarget)view);
9979c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        }
9989171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
9999171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
1000f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        cellLayout.onDropChild(view, mTargetCell);
1001f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
1002f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
1003f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
10046b879f0a5885274a85333531e091283405d490ccAdam Lesinski                LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, lp.cellX, lp.cellY);
10056b879f0a5885274a85333531e091283405d490ccAdam Lesinski    }
10066b879f0a5885274a85333531e091283405d490ccAdam Lesinski
10076b879f0a5885274a85333531e091283405d490ccAdam Lesinski    /**
10086b879f0a5885274a85333531e091283405d490ccAdam Lesinski     * Return the current {@link CellLayout}, correctly picking the destination
10096b879f0a5885274a85333531e091283405d490ccAdam Lesinski     * screen while a scroll is in progress.
10106b879f0a5885274a85333531e091283405d490ccAdam Lesinski     */
10116b879f0a5885274a85333531e091283405d490ccAdam Lesinski    private CellLayout getCurrentDropLayout() {
10126b879f0a5885274a85333531e091283405d490ccAdam Lesinski        int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen;
10136b879f0a5885274a85333531e091283405d490ccAdam Lesinski        return (CellLayout) getChildAt(index);
10146b879f0a5885274a85333531e091283405d490ccAdam Lesinski    }
10156b879f0a5885274a85333531e091283405d490ccAdam Lesinski
10166b879f0a5885274a85333531e091283405d490ccAdam Lesinski    /**
10176b879f0a5885274a85333531e091283405d490ccAdam Lesinski     * {@inheritDoc}
10186b879f0a5885274a85333531e091283405d490ccAdam Lesinski     */
10196b879f0a5885274a85333531e091283405d490ccAdam Lesinski    public boolean acceptDrop(DragSource source, int x, int y,
10206b879f0a5885274a85333531e091283405d490ccAdam Lesinski            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
10216b879f0a5885274a85333531e091283405d490ccAdam Lesinski        final CellLayout layout = getCurrentDropLayout();
10226b879f0a5885274a85333531e091283405d490ccAdam Lesinski        final CellLayout.CellInfo cellInfo = mDragInfo;
10236b879f0a5885274a85333531e091283405d490ccAdam Lesinski        final int spanX = cellInfo == null ? 1 : cellInfo.spanX;
10246b879f0a5885274a85333531e091283405d490ccAdam Lesinski        final int spanY = cellInfo == null ? 1 : cellInfo.spanY;
10256b879f0a5885274a85333531e091283405d490ccAdam Lesinski
10266b879f0a5885274a85333531e091283405d490ccAdam Lesinski        if (mVacantCache == null) {
10276b879f0a5885274a85333531e091283405d490ccAdam Lesinski            final View ignoreView = cellInfo == null ? null : cellInfo.cell;
10286b879f0a5885274a85333531e091283405d490ccAdam Lesinski            mVacantCache = layout.findAllVacantCells(null, ignoreView);
102968d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        }
103068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
103168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        return mVacantCache.findCellForSpan(mTempEstimate, spanX, spanY, false);
103268d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen    }
103368d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
103468d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen    /**
103568d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen     * {@inheritDoc}
103668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen     */
103768d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen    public Rect estimateDropLocation(DragSource source, int x, int y,
103868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen            int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle) {
103968d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        final CellLayout layout = getCurrentDropLayout();
104068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
104168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        final CellLayout.CellInfo cellInfo = mDragInfo;
1042e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        final int spanX = cellInfo == null ? 1 : cellInfo.spanX;
104368d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        final int spanY = cellInfo == null ? 1 : cellInfo.spanY;
104468d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        final View ignoreView = cellInfo == null ? null : cellInfo.cell;
104568d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
104668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        final Rect location = recycle != null ? recycle : new Rect();
104768d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
104868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        // Find drop cell and convert into rectangle
104968d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        int[] dropCell = estimateDropCell(x - xOffset, y - yOffset,
105068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                spanX, spanY, ignoreView, layout, mTempCell);
105168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
105268d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        if (dropCell == null) {
1053f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return null;
1054f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
1055007c69867d821ea2b271398577a8b3440b3a7046Winson Chung
1056007c69867d821ea2b271398577a8b3440b3a7046Winson Chung        layout.cellToPoint(dropCell[0], dropCell[1], mTempEstimate);
1057c3bc26031cc5b36328bd7cdbcf04ff269dea11a5Adam Cohen        location.left = mTempEstimate[0];
1058785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung        location.top = mTempEstimate[1];
1059785d2eb2b8d7072c8124300dd9168ff51a91cf38Winson Chung
1060a2eb17095dcffa75c1e9681fdc318fe6e0564321Michael Jurka        layout.cellToPoint(dropCell[0] + spanX, dropCell[1] + spanY, mTempEstimate);
1061c3bc26031cc5b36328bd7cdbcf04ff269dea11a5Adam Cohen        location.right = mTempEstimate[0];
106221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        location.bottom = mTempEstimate[1];
106368d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
106421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        return location;
10651b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    }
10661b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
1067d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka    /**
106821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen     * Calculate the nearest cell where the given object would be dropped.
106921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen     */
1070f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private int[] estimateDropCell(int pixelX, int pixelY,
1071ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
107221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        // Create vacant cell cache if none exists
107321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        if (mVacantCache == null) {
1074f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            mVacantCache = layout.findAllVacantCells(null, ignoreView);
1075e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        }
1076e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen
1077e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        // Find the best target drop location
1078e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        return layout.findNearestVacantArea(pixelX, pixelY,
1079e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen                spanX, spanY, mVacantCache, recycle);
1080e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen    }
1081e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen
1082e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen    void setLauncher(Launcher launcher) {
1083e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        mLauncher = launcher;
1084e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen    }
1085e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen
10861b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    public void setDragController(DragController dragController) {
108721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mDragController = dragController;
10886b879f0a5885274a85333531e091283405d490ccAdam Lesinski    }
10896b879f0a5885274a85333531e091283405d490ccAdam Lesinski
109068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen    public void onDropCompleted(View target, boolean success) {
10911b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        if (success){
1092f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            if (target != this && mDragInfo != null) {
1093f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
1094f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                cellLayout.removeView(mDragInfo.cell);
1095f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (mDragInfo.cell instanceof DropTarget) {
109600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
109700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
10989c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka                final Object tag = mDragInfo.cell.getTag();
1099956091ba7863bd72086275e61084864994dd6fa7Joe Onorato            }
11009c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        } else {
11019c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            if (mDragInfo != null) {
11029c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
11039c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka                cellLayout.onDropAborted(mDragInfo.cell);
11049c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            }
110500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
110600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
110731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
110828750fba6a2d141eb9a1e566718c17236030b815Michael Jurka    }
1109c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
1110c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    public void scrollLeft() {
1111c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        clearVacantCache();
11120142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextScreen == INVALID_SCREEN && mCurrentScreen > 0 && mScroller.isFinished()) {
1113aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            snapToScreen(mCurrentScreen - 1);
111479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
111579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
1116883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka
1117696a67969d657d38eff33996633f08da0e21841fAdam Cohen    public void scrollRight() {
1118696a67969d657d38eff33996633f08da0e21841fAdam Cohen        clearVacantCache();
1119696a67969d657d38eff33996633f08da0e21841fAdam Cohen        if (mNextScreen == INVALID_SCREEN && mCurrentScreen < getChildCount() -1 &&
1120696a67969d657d38eff33996633f08da0e21841fAdam Cohen                mScroller.isFinished()) {
1121696a67969d657d38eff33996633f08da0e21841fAdam Cohen            snapToScreen(mCurrentScreen + 1);
1122696a67969d657d38eff33996633f08da0e21841fAdam Cohen        }
1123696a67969d657d38eff33996633f08da0e21841fAdam Cohen    }
1124696a67969d657d38eff33996633f08da0e21841fAdam Cohen
112579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    public int getScreenForView(View v) {
112631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int result = -1;
112731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (v != null) {
112831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            ViewParent vp = v.getParent();
11299171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            int count = getChildCount();
1130ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            for (int i = 0; i < count; i++) {
1131c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                if (vp == getChildAt(i)) {
11329171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                    return i;
11339c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka                }
11348d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung            }
1135f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        }
1136f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung        return result;
1137f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung    }
1138f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung
11399171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    /**
1140073a46ff635d089cbcb15d939d1de42dd2b86c97Adam Cohen     * Find a search widget on the given screen
11419171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung     */
11429171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private Search findSearchWidget(CellLayout screen) {
11439171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        final int count = screen.getChildCount();
11449171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        for (int i = 0; i < count; i++) {
11450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View v = screen.getChildAt(i);
1146c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            if (v instanceof Search) {
11470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return (Search) v;
11480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
11490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
11500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return null;
1151a4b4016bcd90da673ba245f83621ef7128fa1cd6Michael Jurka    }
1152a4b4016bcd90da673ba245f83621ef7128fa1cd6Michael Jurka
1153a4b4016bcd90da673ba245f83621ef7128fa1cd6Michael Jurka    /**
11542763be3150d429d338b9848286e9365b4052c100Michael Jurka     * Gets the first search widget on the current screen, if there is one.
11552763be3150d429d338b9848286e9365b4052c100Michael Jurka     * Returns <code>null</code> otherwise.
11560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     */
11570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public Search findSearchWidgetOnCurrentScreen() {
11580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentScreen = (CellLayout)getChildAt(mCurrentScreen);
1159cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        return findSearchWidget(currentScreen);
11600207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy    }
11610207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
11620207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy    public Folder getFolderForTag(Object tag) {
11630207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy        int screenCount = getChildCount();
11640207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy        for (int screen = 0; screen < screenCount; screen++) {
11650207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
11660207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            int count = currentScreen.getChildCount();
11670207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            for (int i = 0; i < count; i++) {
11680207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                View child = currentScreen.getChildAt(i);
11690207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
11700207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
11710207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    Folder f = (Folder) child;
11720207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    if (f.getInfo() == tag) {
117333945b21544bc98381df17726a3537c292d8c985Michael Jurka                        return f;
1174967289b6d5fec77f5c381d11ffb2319f3bb5e737Winson Chung                    }
11750207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                }
11760207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            }
117733945b21544bc98381df17726a3537c292d8c985Michael Jurka        }
1178967289b6d5fec77f5c381d11ffb2319f3bb5e737Winson Chung        return null;
11790207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy    }
11800207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
11810207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy    public View getViewForTag(Object tag) {
11820207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy        int screenCount = getChildCount();
118331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
118431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
118531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
118631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
118731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
1188678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato                if (child.getTag() == tag) {
118931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
119031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
119131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
119231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
11930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return null;
119431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
119531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
119631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
119731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return True is long presses are still allowed for the current touch
119831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
119931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean allowLongPress() {
120097d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung        return mAllowLongPress;
120197d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    }
120297d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung
120397d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    /**
120497d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung     * Set true to allow long-press events to be triggered, usually checked by
120597d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung     * {@link Launcher} to accept or block dpad-initiated long-presses.
120697d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung     */
120797d85d23b013347bead4e2f5fa430a79ce69431eWinson Chung    public void setAllowLongPress(boolean allowLongPress) {
1208c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy        mAllowLongPress = allowLongPress;
1209678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato    }
121031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void removeShortcutsForPackage(String packageName) {
121231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final ArrayList<View> childrenToRemove = new ArrayList<View>();
12130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int count = getChildCount();
12140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
121531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
121631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
121731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int childCount = layout.getChildCount();
121831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            childrenToRemove.clear();
12200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
12210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int j = 0; j < childCount; j++) {
12220142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View view = layout.getChildAt(j);
12230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                Object tag = view.getTag();
12243a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron
1225aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (tag instanceof ApplicationInfo) {
1226dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                    final ApplicationInfo info = (ApplicationInfo) tag;
1227fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell                    // We need to check for ACTION_MAIN otherwise getComponent() might
12280142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                    // return null for some shortcuts (for instance, for shortcuts to
12290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                    // web pages.)
1230fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell                    final Intent intent = info.intent;
12310142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                    final ComponentName name = intent.getComponent();
123231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
123331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
123431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            name != null && packageName.equals(name.getPackageName())) {
123531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
123631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        childrenToRemove.add(view);
123731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
123831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else if (tag instanceof UserFolderInfo) {
1239dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                    final UserFolderInfo info = (UserFolderInfo) tag;
1240dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                    final ArrayList<ApplicationInfo> contents = info.contents;
124131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    final ArrayList<ApplicationInfo> toRemove = new ArrayList<ApplicationInfo>(1);
124231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    final int contentsCount = contents.size();
124331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    boolean removedFromFolder = false;
124431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
124531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    for (int k = 0; k < contentsCount; k++) {
1246ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                        final ApplicationInfo appInfo = contents.get(k);
1247ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                        final Intent intent = appInfo.intent;
1248a7f801fc5b5715223e868ed599da69c5edf436eeMichael Jurka                        final ComponentName name = intent.getComponent();
1249ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka
1250ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                        if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
1251ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                                name != null && packageName.equals(name.getPackageName())) {
1252ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                            toRemove.add(appInfo);
1253ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
1254ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                            removedFromFolder = true;
1255ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                        }
1256ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                    }
1257ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka
1258ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                    contents.removeAll(toRemove);
1259ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                    if (removedFromFolder) {
1260ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                        final Folder folder = getOpenFolder();
1261ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                        if (folder != null) folder.notifyDataSetChanged();
1262ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                    }
1263ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka                }
1264ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            }
12651d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown
12661d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown            childCount = childrenToRemove.size();
12671d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown            for (int j = 0; j < childCount; j++) {
12681d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown                View child = childrenToRemove.get(j);
12691d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown                layout.removeViewInLayout(child);
12701d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown                if (child instanceof DropTarget) {
12711d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown                    mDragController.removeDropTarget((DropTarget)child);
12721d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown                }
12731d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown            }
12741d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown
12751d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown            if (childCount > 0) {
12761d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown                layout.requestLayout();
12771d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown                layout.invalidate();
12781d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown            }
12791d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown        }
128001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
128101f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
128201f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void updateShortcutsForPackage(String packageName) {
128301f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        final PackageManager pm = mLauncher.getPackageManager();
1284a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
1285a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final int count = getChildCount();
1286a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        for (int i = 0; i < count; i++) {
1287a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            final CellLayout layout = (CellLayout) getChildAt(i);
1288a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            int childCount = layout.getChildCount();
1289a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            for (int j = 0; j < childCount; j++) {
1290a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                final View view = layout.getChildAt(j);
1291a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                Object tag = view.getTag();
1292a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                if (tag instanceof ApplicationInfo) {
1293a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                    ApplicationInfo info = (ApplicationInfo) tag;
1294a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                    // We need to check for ACTION_MAIN otherwise getComponent() might
1295a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                    // return null for some shortcuts (for instance, for shortcuts to
1296af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka                    // web pages.)
1297af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka                    final Intent intent = info.intent;
1298af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka                    final ComponentName name = intent.getComponent();
12999171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
13003c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null &&
1301af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka                            packageName.equals(name.getPackageName())) {
1302af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka
1303883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                        final Drawable icon = AppInfoCache.getIconDrawable(pm, info);
1304883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                        if (icon != null && icon != info.icon) {
1305883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                            info.icon.setCallback(null);
1306883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                            info.icon = Utilities.createIconThumbnail(icon, mContext);
1307883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                            info.filtered = true;
1308883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                            ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
1309af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka                                    info.icon, null, null);
1310883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                        }
1311883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                    }
13123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                }
1313a997ac26664befbd0d5b172e36ef9e8b2c63b435Michael Jurka            }
13143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
13151b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    }
13160dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy
13170dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy    void moveToDefaultScreen() {
13180dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        snapToScreen(mDefaultScreen);
13190dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        getChildAt(mDefaultScreen).requestFocus();
13200dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy    }
1321ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen
1322ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen    public static class SavedState extends BaseSavedState {
1323ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen        int currentScreen = -1;
13241b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
13251b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        SavedState(Parcelable superState) {
13260dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy            super(superState);
13270dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        }
13280dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy
13290dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        private SavedState(Parcel in) {
13300dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy            super(in);
13310dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy            currentScreen = in.readInt();
13320dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        }
13337247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy
1334dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        @Override
1335213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        public void writeToParcel(Parcel out, int flags) {
13360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.writeToParcel(out, flags);
1337244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy            out.writeInt(currentScreen);
1338244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy        }
1339244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy
13400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        public static final Parcelable.Creator<SavedState> CREATOR =
13410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                new Parcelable.Creator<SavedState>() {
13420142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            public SavedState createFromParcel(Parcel in) {
13430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return new SavedState(in);
1344244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy            }
1345244d74cb353f1260c4d633e719bf84bb3b6e52bcPatrick Dubroy
1346a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            public SavedState[] newArray(int size) {
1347dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                return new SavedState[size];
1348dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
1349a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        };
1350213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
1351df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung
1352742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    void show() {
1353ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung        setVisibility(VISIBLE);
1354ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung    }
13553e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
13563e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    void hide() {
1357f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen    }
1358af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka}
1359742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka