Workspace.java revision 6569f2c80e179c2f8ed73dae6b01d971ec20f005
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
198edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurkaimport com.android.launcher.R;
208edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka
21495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.app.WallpaperManager;
220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.appwidget.AppWidgetManager;
238edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurkaimport android.appwidget.AppWidgetProviderInfo;
24b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.content.ComponentName;
250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.content.Context;
26cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.content.Intent;
27cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.content.pm.PackageManager;
288edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurkaimport android.content.pm.ProviderInfo;
29cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.content.res.TypedArray;
3068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport android.graphics.Canvas;
318f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.graphics.Paint;
32629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.graphics.Rect;
33629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.graphics.drawable.Drawable;
34a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.net.Uri;
35a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.os.IBinder;
36495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcel;
3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Parcelable;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
39495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.util.Log;
405c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.view.MotionEvent;
417247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.view.VelocityTracker;
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.view.ViewConfiguration;
446b879f0a5885274a85333531e091283405d490ccAdam Lesinskiimport android.view.ViewGroup;
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.ViewParent;
46a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.view.animation.Animation;
47a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.animation.Animation.AnimationListener;
4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.animation.Interpolator;
49a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.animation.RotateAnimation;
504be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.widget.Scroller;
51f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
525c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.widget.Toast;
53956091ba7863bd72086275e61084864994dd6fa7Joe Onorato
54495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport java.util.ArrayList;
5531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport java.util.HashSet;
56291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler
57580e27748137ff08599aa719d106b31215a28353Winson Chung/**
58a34abf8c781485b788fddacb352d586bffca886cWinson Chung * The workspace is a wide area with a wallpaper and a finite number of screens.
59a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung * Each screen contains a number of icons, folders or widgets the user can
6031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * interact with. A workspace is meant to be used with a fixed width only.
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
626e3140865d3f0def2e55934d8b0b2c1503386e54Winson Chungpublic class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller {
63cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    @SuppressWarnings({"UnusedDeclaration"})
643c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka    private static final String TAG = "Launcher.Workspace";
653c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka    private static final int INVALID_SCREEN = -1;
66f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
67a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * The velocity at which a fling gesture will cause us to snap to the next
698edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka     * screen
708edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka     */
718edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka    private static final int SNAP_VELOCITY = 600;
72edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
7331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final WallpaperManager mWallpaperManager;
740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultScreen;
76aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mFirstLayout = true;
780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
79e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    private int mCurrentScreen;
80e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    private int mNextScreen = INVALID_SCREEN;
81e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    private Scroller mScroller;
823a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private VelocityTracker mVelocityTracker;
830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
84dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    /**
85dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka     * CellInfo for the cell that is currently being dragged
86dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka     */
87a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private CellLayout.CellInfo mDragInfo;
88d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka
89d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka    /**
90d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka     * Target drop area calculated during last acceptDrop call.
91f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen     */
92f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private int[] mTargetCell = null;
93a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
94a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    /**
95a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen     * The CellLayout that is currently being dragged over
961b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen     */
97a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private CellLayout mDragTargetLayout = null;
981b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
99a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float mLastMotionX;
10068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen    private float mLastMotionY;
10168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
1029171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private final static int TOUCH_STATE_REST = 0;
103f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private final static int TOUCH_STATE_SCROLLING = 1;
104f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung
1059171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private int mTouchState = TOUCH_STATE_REST;
1069171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
1079171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private OnTouchListener mInterceptTouchListener;
1089171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private OnLongClickListener mLongClickListener;
1099171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
1109171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private Launcher mLauncher;
1119171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private IconCache mIconCache;
1129171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    private DragController mDragController;
113e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka
114e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka    /**
1159171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung     * Cache of vacant cells, used during drag events and invalidated as needed.
1168d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung     */
11725356e75ebae5d6e0be43f38d2c73b5cb59d05f2Michael Jurka    private CellLayout.CellInfo mVacantCache = null;
1188d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung
119f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private int[] mTempCell = new int[2];
12068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen    private int[] mTempEstimate = new int[2];
121e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen
122f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private boolean mAllowLongPress = true;
12388127038178b3bbf0eb91103a31e682cc0615074Winson Chung
12488127038178b3bbf0eb91103a31e682cc0615074Winson Chung    private int mTouchSlop;
12588127038178b3bbf0eb91103a31e682cc0615074Winson Chung    private int mMaximumVelocity;
12688127038178b3bbf0eb91103a31e682cc0615074Winson Chung
12788127038178b3bbf0eb91103a31e682cc0615074Winson Chung    private static final int INVALID_POINTER = -1;
1288f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn
1299c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka    private int mActivePointerId = INVALID_POINTER;
130aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1310142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private Drawable mPreviousIndicator;
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Drawable mNextIndicator;
133d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka
13421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    private static final float NANOTIME_DIV = 1000000000.0f;
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final float SMOOTHING_SPEED = 0.75f;
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED));
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private float mSmoothingTime;
13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private float mTouchX;
139aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
14070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private WorkspaceOvershootInterpolator mScrollInterpolator;
14170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
14270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private static final float BASELINE_FLING_VELOCITY = 2500.f;
14370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private static final float FLING_VELOCITY_INFLUENCE = 0.4f;
14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1456569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private Paint mDropIndicatorPaint;
1466569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1476569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private static class WorkspaceOvershootInterpolator implements Interpolator {
1486569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        private static final float DEFAULT_TENSION = 1.3f;
1496569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        private float mTension;
15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1510589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        public WorkspaceOvershootInterpolator() {
15200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mTension = DEFAULT_TENSION;
153aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
1544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
1554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        public void setDistance(int distance) {
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION;
15770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        }
1580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
159a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        public void disableSettle() {
1604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mTension = 0.f;
1614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        }
162a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        public float getInterpolation(float t) {
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // _o(t) = t * t * ((tension + 1) * t + tension)
165c2f7f4794867cd1b3e97fd0f379ad8ad15958a6cMichael Jurka            // o(t) = _o(t - 1) + 1
166d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka            t -= 1.0f;
167d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen            return t * t * ((mTension + 1) * t + mTension) + 1.0f;
168d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        }
16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1708a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
1718a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    /**
172aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     * Used to inflate the Workspace from XML.
1731262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy     *
174dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka     * @param context The application's context.
175c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka     * @param attrs The attribtues set containing the Workspace's customization values.
176c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka     */
177bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka    public Workspace(Context context, AttributeSet attrs) {
178b8e14479da7209ca811a753b3256fe4a0b49a873Michael Jurka        this(context, attrs, 0);
179af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka    }
180af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka
181d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka    /**
182883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka     * Used to inflate the Workspace from XML.
183af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka     *
1843c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka     * @param context The application's context.
185dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka     * @param attrs The attribtues set containing the Workspace's customization values.
18654fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy     * @param defStyle Unused.
1871262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy     */
1881262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public Workspace(Context context, AttributeSet attrs, int defStyle) {
18954fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy        super(context, attrs, defStyle);
19054fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy
19154fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy        mWallpaperManager = WallpaperManager.getInstance(context);
1928e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy
1934be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        TypedArray a = context.obtainStyledAttributes(attrs,
1948e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy                R.styleable.Workspace, defStyle, 0);
1958e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        int canonicalDeviceWidth = a.getInt(R.styleable.Workspace_canonicalDeviceWidth, 4);
1964be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        int canonicalDeviceHeight = a.getInt(R.styleable.Workspace_canonicalDeviceHeight, 4);
197cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDefaultScreen = a.getInt(R.styleable.Workspace_defaultScreen, 1);
198cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        a.recycle();
199cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
200cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        LauncherModel.updateWorkspaceLayoutCells(canonicalDeviceWidth,
201cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canonicalDeviceHeight);
202a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        setHapticFeedbackEnabled(false);
203a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        initWorkspace();
204a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
2056b879f0a5885274a85333531e091283405d490ccAdam Lesinski
2066b879f0a5885274a85333531e091283405d490ccAdam Lesinski    /**
2076b879f0a5885274a85333531e091283405d490ccAdam Lesinski     * Initializes various states for this workspace.
2086b879f0a5885274a85333531e091283405d490ccAdam Lesinski     */
2096b879f0a5885274a85333531e091283405d490ccAdam Lesinski    private void initWorkspace() {
210c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        Context context = getContext();
211c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        mScrollInterpolator = new WorkspaceOvershootInterpolator();
212c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        mScroller = new Scroller(context, mScrollInterpolator);
213ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        mCurrentScreen = mDefaultScreen;
214c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        Launcher.setScreen(mCurrentScreen);
215ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
216c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        mIconCache = app.getIconCache();
2170bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka
2180bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
2190bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka        mTouchSlop = configuration.getScaledTouchSlop();
2200bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
2210bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka    }
2220bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka
2230bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka    @Override
224f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen    public void addView(View child, int index, LayoutParams params) {
225f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        if (!(child instanceof CellLayout)) {
226f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
227f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        }
228f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        super.addView(child, index, params);
229f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen    }
230f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
2350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
24231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
2450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
2500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
2515f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
2525f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        super.addView(child, width, height);
2535f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
2545f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
2568f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    public void addView(View child, LayoutParams params) {
257aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (!(child instanceof CellLayout)) {
258aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
259aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
260d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        super.addView(child, params);
261d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    }
2620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
265d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen     */
2660d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato    Folder getOpenFolder() {
2670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen);
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int count = currentScreen.getChildCount();
269c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung        for (int i = 0; i < count; i++) {
270c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung            View child = currentScreen.getChildAt(i);
271c35afb2c9df8cc56c77bf21ce2eaa213f6f31251Winson Chung            if (child instanceof Folder) {
27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                Folder folder = (Folder) child;
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (folder.getInfo().opened)
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return folder;
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
2770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return null;
2780589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
2790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
2800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    ArrayList<Folder> getOpenFolders() {
2810589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        final int screens = getChildCount();
2820589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        ArrayList<Folder> folders = new ArrayList<Folder>(screens);
283a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
284cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        for (int screen = 0; screen < screens; screen++) {
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = (CellLayout) getChildAt(screen);
286b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung            int count = currentScreen.getChildCount();
287b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung            for (int i = 0; i < count; i++) {
288b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung                View child = currentScreen.getChildAt(i);
2898d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child
290b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung                        .getLayoutParams();
291b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung                if (child instanceof Folder) {
292b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung                    Folder folder = (Folder) child;
2939171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                    if (folder.getInfo().opened)
2948edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka                        folders.add(folder);
2953c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                    break;
296c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                }
297c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            }
298c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        }
2990bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka
3003c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        return folders;
3018edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka    }
302c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka
303ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    boolean isDefaultScreenShowing() {
3040bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka        return mCurrentScreen == mDefaultScreen;
3050bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka    }
3060bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka
3070bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka    /**
3080bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka     * Returns the index of the currently displayed screen.
3090bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka     *
3100bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka     * @return The index of the currently displayed screen.
3110bb8563b1381d92b0d7dbb5b0f814ad656c2f9bdMichael Jurka     */
312a58f8bb1947af39d4d18d849b3e4d6bd0d3954d7Winson Chung    int getCurrentScreen() {
313a58f8bb1947af39d4d18d849b3e4d6bd0d3954d7Winson Chung        return mCurrentScreen;
314ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka    }
31560b7c53ccc6384b65aaca77d97794e8f09e8cfc8Patrick Dubroy
316ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka    /**
317bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka     * Sets the current screen.
318bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka     *
319bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka     * @param currentScreen
320bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka     */
321ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka    void setCurrentScreen(int currentScreen) {
322ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        if (!mScroller.isFinished())
323ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            mScroller.abortAnimation();
324ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        clearVacantCache();
325bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka        mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1));
326ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka        if (mPreviousIndicator != null) {
32760b7c53ccc6384b65aaca77d97794e8f09e8cfc8Patrick Dubroy            mPreviousIndicator.setLevel(mCurrentScreen);
328dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            mNextIndicator.setLevel(mCurrentScreen);
329dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
3300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
331ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        scrollTo(mCurrentScreen * getWidth(), 0);
33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        updateWallpaperOffset();
33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        invalidate();
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
335f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
336f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    /**
337e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen     * Adds the specified child in the current screen. The position and dimension of
338f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen     * the child are defined by x, y, spanX and spanY.
339e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen     *
340f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen     * @param child The child to add in one of the workspace's screens.
341f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen     * @param x The X position of the child in the screen's grid.
342f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen     * @param y The Y position of the child in the screen's grid.
343f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen     * @param spanX The number of cells spanned horizontally by the child.
34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInCurrentScreen(View child, int x, int y, int spanX, int spanY) {
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, mCurrentScreen, x, y, spanX, spanY, false);
34821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    }
349e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
350e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    /**
35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the current screen. The position and dimension of
35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
35921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen     * @param insert When true, the child is inserted at the beginning of the children list.
360e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy     */
361e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    void addInCurrentScreen(View child, int x, int y, int spanX, int spanY, boolean insert) {
36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, mCurrentScreen, x, y, spanX, spanY, insert);
36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
36931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
37021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen     * @param screen The screen in which to add the child.
371e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy     * @param x The X position of the child in the screen's grid.
372e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy     * @param y The Y position of the child in the screen's grid.
37331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
37431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
37531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
37831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
37931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInFullScreen(View child, int screen) {
38121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        addInScreen(child, screen, 0, 0, -1, -1);
382e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    }
383e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void rotateCurrentScreensChildren() {
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // close all the folders first
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final ArrayList<Folder> openFolders = getOpenFolders();
38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        WorkspaceOvershootInterpolator wi = new WorkspaceOvershootInterpolator();
39031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        RotateAnimation ra = new RotateAnimation((float) LauncherModel
39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                .getPreviousOrientationRelativeToCurrent(), 0,
39221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
393e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy                0.5f);
394e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        ra.setInterpolator(wi);
39531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen);
39631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ra.setStartOffset(150);
39731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ra.setDuration(650 + (int) (Math.random() * 400) - 200);
39831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
39931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.CellLayoutAnimationController animationController = new CellLayout.CellLayoutAnimationController(
40031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                ra, 0.0f);
40131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        currentScreen.setLayoutAnimation(animationController);
4026e3140865d3f0def2e55934d8b0b2c1503386e54Winson Chung        currentScreen.setLayoutAnimationListener(new AnimationListener() {
4030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            public void onAnimationStart(Animation animation) {
40431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // do nothing
4050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
406aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
407aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            public void onAnimationRepeat(Animation animation) {
408aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // do nothing
409aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            }
41031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
41131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            public void onAnimationEnd(Animation animation) {
41231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                for (int j = 0; j < openFolders.size(); ++j) {
41331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder folder = openFolders.get(j);
41431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (!folder.getInfo().opened) {
41531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mLauncher.openFolder(folder.getInfo());
416dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                    }
417dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                }
41831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
419dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        });
4206e3140865d3f0def2e55934d8b0b2c1503386e54Winson Chung        animationController.start();
4210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
42231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int j = 0; j < openFolders.size(); ++j) {
4230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mLauncher.closeFolder(openFolders.get(j));
424aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
425aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
426aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
427aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void refreshWorkspaceChildren() {
42831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int count = getChildCount();
42931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child;
43031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp;
43231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int widthMeasureSpec = MeasureSpec.makeMeasureSpec(LauncherModel
43331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                .getLocalDeviceWidth(), MeasureSpec.EXACTLY);
43431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int heightMeasureSpec = MeasureSpec.makeMeasureSpec(LauncherModel
435a0aa0121b91fde17e427ab2763ce312e64cf5d33Patrick Dubroy                .getLocalDeviceHeight(), MeasureSpec.EXACTLY);
436a0aa0121b91fde17e427ab2763ce312e64cf5d33Patrick Dubroy
43731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        clearVacantCache();
43831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
44031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
44131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int numChildren = layout.getChildCount();
44231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
44331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // save reference to all current children
44431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int j = 0; j < numChildren; j++) {
44531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                child = layout.getChildAt(j);
44631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
44731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                lp = (CellLayout.LayoutParams) child.getLayoutParams();
44831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                LauncherModelOrientationHelper.Coordinates localCoord = LauncherModel
44931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        .getLocalCoordinatesFromPreviousLocalCoordinates(lp);
45031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
45131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                lp.cellX = localCoord.x;
45231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                lp.cellY = localCoord.y;
45331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
454aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
455aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            layout.measure(widthMeasureSpec, heightMeasureSpec);
456aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
457aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
45831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
45931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
46031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
46131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
46231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
46331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
46431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
46531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
46631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
46731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
46831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
46931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
47031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
47131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
472291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler        if (screen < 0 || screen >= getChildCount()) {
473291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
474291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
47531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
47631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
47731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
47831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        clearVacantCache();
47931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
48031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
48131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
48231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
48331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
48431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
48531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
48631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
487aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            lp.cellHSpan = spanX;
4886569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            lp.cellVSpan = spanY;
489845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        }
490f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka
491f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        // Get the canonical child id to uniquely represent this view in this screen
492aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        int childId = LauncherModel.getCanonicalCellLayoutChildId(child.getId(), screen, x, y, spanX, spanY);
493aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
4946569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // TODO: This branch occurs when the workspace is adding views
495aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
496aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // maybe we should be deleting these items from the LauncherModel?
497aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
49831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
4990d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato
50031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
50131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setHapticFeedbackEnabled(false);
50200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            child.setOnLongClickListener(mLongClickListener);
503aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
50400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
50531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mDragController.addDropTarget((DropTarget) child);
50631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
507d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    }
508d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy
509d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    CellLayout.CellInfo findAllVacantCells(boolean[] occupied) {
510d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        CellLayout group = (CellLayout) getChildAt(mCurrentScreen);
511d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        if (group != null) {
512d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            return group.findAllVacantCells(occupied, null);
513d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        }
514d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        return null;
515d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    }
516d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy
517d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    private void clearVacantCache() {
518d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        if (mVacantCache != null) {
519d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            mVacantCache.clearVacantCells();
520d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy            mVacantCache = null;
521d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        }
522d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    }
523d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy
524d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    public void setOnInterceptTouchListener(View.OnTouchListener listener) {
525d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        mInterceptTouchListener = listener;
526d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    }
527d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy
528d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    /**
529d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy     * Registers the specified listener on each screen contained in this workspace.
530d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy     *
531d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy     * @param l The listener used to respond to long clicks.
532d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy     */
533d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    @Override
534d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy    public void setOnLongClickListener(OnLongClickListener l) {
535d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        mLongClickListener = l;
536d0ce1ec2e21ce3bb0ba3549a01d1d06b440a8e45Patrick Dubroy        final int count = getChildCount();
537e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        for (int i = 0; i < count; i++) {
538e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy            getChildAt(i).setOnLongClickListener(l);
539e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        }
540e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    }
541e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
542e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    private void updateWallpaperOffset() {
543dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
544e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    }
545e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
546e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    private void updateWallpaperOffset(int scrollRange) {
547e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        IBinder token = getWindowToken();
548e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        if (token != null) {
549e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy            mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
550e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy            mWallpaperManager.setWallpaperOffsets(getWindowToken(),
551e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy                    Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
552e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        }
553e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy    }
554e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy
555dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    @Override
5560e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    public void scrollTo(int x, int y) {
5570e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        super.scrollTo(x, y);
558ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen        mTouchX = x;
559ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
560ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen    }
561ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen
5625f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
5635f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public void computeScroll() {
564c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mScroller.computeScrollOffset()) {
5655f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mTouchX = mScrollX = mScroller.getCurrX();
5665f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
5675f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mScrollY = mScroller.getCurrY();
5685f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            updateWallpaperOffset();
5695f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            postInvalidate();
5705f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        } else if (mNextScreen != INVALID_SCREEN) {
5715f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1));
5725f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            if (mPreviousIndicator != null) {
573f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen                mPreviousIndicator.setLevel(mCurrentScreen);
574f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen                mNextIndicator.setLevel(mCurrentScreen);
575f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            }
576f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            Launcher.setScreen(mCurrentScreen);
577f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen            mNextScreen = INVALID_SCREEN;
578c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            clearChildrenCache();
579e708c5249b26978057acb9370cbfb8f6f747f5b8Patrick Dubroy        } else if (mTouchState == TOUCH_STATE_SCROLLING) {
5806b879f0a5885274a85333531e091283405d490ccAdam Lesinski            final float now = System.nanoTime() / NANOTIME_DIV;
5816b879f0a5885274a85333531e091283405d490ccAdam Lesinski            final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT);
582be9093426aec3a6d412811a12d2400e645613242Adam Cohen            final float dx = mTouchX - mScrollX;
583be9093426aec3a6d412811a12d2400e645613242Adam Cohen            mScrollX += dx * e;
584be9093426aec3a6d412811a12d2400e645613242Adam Cohen            mSmoothingTime = now;
585be9093426aec3a6d412811a12d2400e645613242Adam Cohen
586be9093426aec3a6d412811a12d2400e645613242Adam Cohen            // Keep generating points as long as we're more than 1px away from the target
5876b879f0a5885274a85333531e091283405d490ccAdam Lesinski            if (dx > 1.f || dx < -1.f) {
5886b879f0a5885274a85333531e091283405d490ccAdam Lesinski                updateWallpaperOffset();
5895f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                postInvalidate();
5905f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            }
5915f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
5925f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
5935f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
5941adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    @Override
5951adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    protected void dispatchDraw(Canvas canvas) {
59669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        boolean restore = false;
59769c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        int restoreCount = 0;
59869c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen
599f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        // ViewGroup.dispatchDraw() supports many features we don't need:
60069c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        // clip to padding, layout animation, animation listener, disappearing
601f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        // children, etc. The following implementation attempts to fast-track
60269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        // the drawing dispatch by drawing only what we know needs to be drawn.
60369c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen
604f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN;
60569c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        // If we are not scrolling or flinging, draw only the current screen
60669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        if (fastDraw) {
60769c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());
608f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen        } else {
60969c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            final long drawingTime = getDrawingTime();
61069c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            final float scrollPos = (float) mScrollX / getWidth();
61169c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            final int leftScreen = (int) scrollPos;
61269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            final int rightScreen = leftScreen + 1;
61369c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            if (leftScreen >= 0) {
61469c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen                drawChild(canvas, getChildAt(leftScreen), drawingTime);
61569c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            }
61669c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            if (scrollPos != leftScreen && rightScreen < getChildCount()) {
61769c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen                drawChild(canvas, getChildAt(rightScreen), drawingTime);
61869c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            }
61969c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        }
62069c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen
62169c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        if (restore) {
62269c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen            canvas.restoreToCount(restoreCount);
62369c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen        }
62469c42da4d30f1cbba5fe1ac8960b4e305e14b807Adam Cohen    }
625f8d2823d885ba682140aee1ae0504c1c5e67a24bAdam Cohen
6261adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    protected void onAttachedToWindow() {
6271adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka        super.onAttachedToWindow();
6281262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        computeScroll();
6290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragController.setWindowToken(getWindowToken());
6300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
63116fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka
6320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
6330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
6340142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
63516fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka
63631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int width = MeasureSpec.getSize(widthMeasureSpec);
637f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
63831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (widthMode != MeasureSpec.EXACTLY) {
63931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
6401262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
64116fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka
6421262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
6431262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (heightMode != MeasureSpec.EXACTLY) {
6441262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
6451262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
64668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
647e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        // The children are given the same width and height as the workspace
6480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int count = getChildCount();
6490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = 0; i < count; i++) {
6500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
6510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
6520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mFirstLayout) {
6540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setHorizontalScrollBarEnabled(false);
6550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            scrollTo(mCurrentScreen * width, 0);
6560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setHorizontalScrollBarEnabled(true);
6570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            updateWallpaperOffset(width * (getChildCount() - 1));
6580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mFirstLayout = false;
6590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
6600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
6610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
6630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
6640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int childLeft = 0;
6650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int count = getChildCount();
667c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        for (int i = 0; i < count; i++) {
668c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            final View child = getChildAt(i);
669c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            if (child.getVisibility() != View.GONE) {
670c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                final int childWidth = child.getMeasuredWidth();
671c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
672c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                childLeft += childWidth;
673c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            }
674c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        }
675c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
676c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        if (LauncherApplication.isInPlaceRotationEnabled()) {
677c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            // When the device is rotated, the scroll position of the current screen
678c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            // needs to be refreshed
679c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            setCurrentScreen(getCurrentScreen());
680c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        }
681c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    }
682c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
683c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    @Override
684c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
685c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        int screen = indexOfChild(child);
686c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        if (screen != mCurrentScreen || !mScroller.isFinished()) {
687c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            if (!mLauncher.isWorkspaceLocked()) {
688c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                snapToScreen(screen);
689c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            }
690c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            return true;
691c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        }
692c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        return false;
693c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    }
694c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
695c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    @Override
696c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
697c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        if (!mLauncher.isAllAppsVisible()) {
698c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            final Folder openFolder = getOpenFolder();
699c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            if (openFolder != null) {
700c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                return openFolder.requestFocus(direction, previouslyFocusedRect);
701c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            } else {
702c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                int focusableScreen;
703c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                if (mNextScreen != INVALID_SCREEN) {
704c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                    focusableScreen = mNextScreen;
705c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                } else {
706c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                    focusableScreen = mCurrentScreen;
707c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                }
708c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                getChildAt(focusableScreen).requestFocus(direction, previouslyFocusedRect);
709c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            }
710c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        }
711c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        return false;
712c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka    }
713c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
714f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung    @Override
715f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung    public boolean dispatchUnhandledMove(View focused, int direction) {
716f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung        if (direction == View.FOCUS_LEFT) {
717f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung            if (getCurrentScreen() > 0) {
718f7640c8bba304ba99c99afcd7393893eccc9a0d9Winson Chung                snapToScreen(getCurrentScreen() - 1);
719c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka                return true;
720c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            }
721ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        } else if (direction == View.FOCUS_RIGHT) {
722ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            if (getCurrentScreen() < getChildCount() - 1) {
723ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                snapToScreen(getCurrentScreen() + 1);
724ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                return true;
725ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            }
726ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
727ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
728ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    }
729ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
730ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    @Override
731ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
732c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        if (!mLauncher.isAllAppsVisible()) {
733c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            final Folder openFolder = getOpenFolder();
734ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            if (openFolder == null) {
735ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                getChildAt(mCurrentScreen).addFocusables(views, direction);
736f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka                if (direction == View.FOCUS_LEFT) {
737ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    if (mCurrentScreen > 0) {
738ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        getChildAt(mCurrentScreen - 1).addFocusables(views, direction);
739ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    }
740ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                } else if (direction == View.FOCUS_RIGHT) {
741ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    if (mCurrentScreen < getChildCount() - 1) {
742f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka                        getChildAt(mCurrentScreen + 1).addFocusables(views, direction);
743f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka                    }
744f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka                }
745ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            } else {
746ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                openFolder.addFocusables(views, direction);
747ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            }
748ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
749ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    }
750ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
75109d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka    @Override
75209d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka    public boolean dispatchTouchEvent(MotionEvent ev) {
75309d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
75409d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka            if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) {
75509d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka                return false;
75609d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka            }
75709d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        }
75809d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        return super.dispatchTouchEvent(ev);
75909d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka    }
76009d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka
76109d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka    @Override
76209d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
76309d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        if (mInterceptTouchListener != null && mInterceptTouchListener.onTouch(this, ev)) {
764ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            return true;
76509d6eb0f3fb1d81ea59881e6c65512d09d573cc1Michael Jurka        }
766ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final boolean workspaceLocked = mLauncher.isWorkspaceLocked();
767f70c78142457b0e9c691f2a20ed87407c7433f5bMichael Jurka        final boolean allAppsVisible = mLauncher.isAllAppsVisible();
768ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        if (workspaceLocked || allAppsVisible) {
769ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            return false; // We don't want the events.  Let them fall through to the all apps view.
770ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
771ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
772340c5f3a708efa280a120708594247952ca65182Michael Jurka        /*
773ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka         * This method JUST determines whether we want to intercept the motion.
774c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * If we return true, onTouchEvent will be called and we do the actual
775c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * scrolling there.
776c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         */
777c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
778c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        /*
779c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * Shortcut the most recurring case: the user is in the dragging
780c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka         * state and he is moving his finger.  We want to intercept this
781ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka         * motion.
782ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka         */
783ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final int action = ev.getAction();
784ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) {
785ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            return true;
786ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
787ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
788ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        if (mVelocityTracker == null) {
789c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            mVelocityTracker = VelocityTracker.obtain();
790ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
791ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        mVelocityTracker.addMovement(ev);
792ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
7939c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        switch (action & MotionEvent.ACTION_MASK) {
7949c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            case MotionEvent.ACTION_MOVE: {
795ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                /*
796ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
797ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 * whether the user has moved far enough from his original down touch.
798ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 */
7992763be3150d429d338b9848286e9365b4052c100Michael Jurka
800956091ba7863bd72086275e61084864994dd6fa7Joe Onorato                /*
801ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 * Locally do absolute value. mLastMotionX is set to the y value
802ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 * of the down event.
803ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                 */
804ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
805ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                final float x = ev.getX(pointerIndex);
806ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                final float y = ev.getY(pointerIndex);
807ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                final int xDiff = (int) Math.abs(x - mLastMotionX);
808ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                final int yDiff = (int) Math.abs(y - mLastMotionY);
809ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
810ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                final int touchSlop = mTouchSlop;
811ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                boolean xMoved = xDiff > touchSlop;
812ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                boolean yMoved = yDiff > touchSlop;
813ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
814ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                if (xMoved || yMoved) {
815ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
816ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    if (xMoved) {
817ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        // Scroll if the user moved far enough along the X axis
818ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        mTouchState = TOUCH_STATE_SCROLLING;
819ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        mLastMotionX = x;
820ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        mTouchX = mScrollX;
821ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
822ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1);
823ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    }
824ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    // Either way, cancel any pending longpress
825ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    if (mAllowLongPress) {
826ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        mAllowLongPress = false;
827ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        // Try canceling the long press. It could also have been scheduled
828ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        // by a distant descendant, so use the mAllowLongPress flag to block
829ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        // everything
830ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        final View currentScreen = getChildAt(mCurrentScreen);
831ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        currentScreen.cancelLongPress();
832ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    }
833ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                }
834ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                break;
835ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            }
836ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
837ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        case MotionEvent.ACTION_DOWN: {
838ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            final float x = ev.getX();
839ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            final float y = ev.getY();
840ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            // Remember location of down touch
841ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            mLastMotionX = x;
842ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            mLastMotionY = y;
843ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            mActivePointerId = ev.getPointerId(0);
844ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            mAllowLongPress = true;
845ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
846ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                /*
847ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                 * If being flinged and user touches the screen, initiate drag;
848ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                 * otherwise don't.  mScroller.isFinished should be false when
849ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                 * being flinged.
850ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                 */
851ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
852ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                break;
853ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            }
854ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
855ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            case MotionEvent.ACTION_CANCEL:
856ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka            case MotionEvent.ACTION_UP:
857ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
858ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                if (mTouchState != TOUCH_STATE_SCROLLING) {
859ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    final CellLayout currentScreen = (CellLayout)getChildAt(mCurrentScreen);
860ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    if (!currentScreen.lastDownOnOccupiedCell()) {
861ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                        getLocationOnScreen(mTempCell);
862ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        // Send a tap to the wallpaper if the last down was on empty space
863ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
864ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        mWallpaperManager.sendWallpaperCommand(getWindowToken(),
865ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                "android.wallpaper.tap",
866ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                mTempCell[0] + (int) ev.getX(pointerIndex),
867ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                mTempCell[1] + (int) ev.getY(pointerIndex), 0, null);
868ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    }
869ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                }
870ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
871ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                // Release the drag
872ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                clearChildrenCache();
873ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                mTouchState = TOUCH_STATE_REST;
874ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mActivePointerId = INVALID_POINTER;
875ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                mAllowLongPress = false;
876ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
877ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                if (mVelocityTracker != null) {
878ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    mVelocityTracker.recycle();
879ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                    mVelocityTracker = null;
880ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                }
881ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
882ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            break;
883ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
884ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        case MotionEvent.ACTION_POINTER_UP:
885ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            onSecondaryPointerUp(ev);
886ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            break;
887ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
888ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
889ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        /*
890ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka         * The only time we want to intercept motion events is if we are in the
891ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka         * drag mode.
892ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka         */
893ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        return mTouchState != TOUCH_STATE_REST;
894ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    }
895ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
896ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka    private void onSecondaryPointerUp(MotionEvent ev) {
897ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
898ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
899ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        final int pointerId = ev.getPointerId(pointerIndex);
900ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        if (pointerId == mActivePointerId) {
901ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            // This was our active pointer going up. Choose a new
902ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            // active pointer and adjust accordingly.
903ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            // TODO: Make this decision more intelligent.
904ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
905ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            mLastMotionX = ev.getX(newPointerIndex);
906ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            mLastMotionY = ev.getY(newPointerIndex);
907ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            mActivePointerId = ev.getPointerId(newPointerIndex);
908ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            if (mVelocityTracker != null) {
909ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                mVelocityTracker.clear();
910ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka            }
911ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka        }
9128f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
913aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
914340c5f3a708efa280a120708594247952ca65182Michael Jurka    /**
915340c5f3a708efa280a120708594247952ca65182Michael Jurka     * If one of our descendant views decides that it could be focused now, only
916340c5f3a708efa280a120708594247952ca65182Michael Jurka     * pass that along if it's on the current screen.
917ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka     *
918ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka     * This happens when live folders requery, and if they're off screen, they
919ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka     * end up calling requestFocus, which pulls it on screen.
920340c5f3a708efa280a120708594247952ca65182Michael Jurka     */
921340c5f3a708efa280a120708594247952ca65182Michael Jurka    @Override
92294f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy    public void focusableViewAvailable(View focused) {
9233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        View current = getChildAt(mCurrentScreen);
9249171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        View v = focused;
9259171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        while (true) {
9269171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            if (v == current) {
9279171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                super.focusableViewAvailable(focused);
9289171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                return;
9293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
930f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            if (v == this) {
931f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                return;
93294f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy            }
9333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ViewParent parent = v.getParent();
9349171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            if (parent instanceof View) {
9359171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                v = (View) v.getParent();
9369171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            } else {
9379171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                return;
9389171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            }
9399171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        }
9403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
941f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
942f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    void enableChildrenCache(int fromScreen, int toScreen) {
94394f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy        if (fromScreen > toScreen) {
94494f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy            final int temp = fromScreen;
94594f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy            fromScreen = toScreen;
94694f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy            toScreen = temp;
94794f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy        }
94894f78a5c44c08b258f59b2c78ff6694e5eaca827Patrick Dubroy
9499171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        final int count = getChildCount();
9509171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
951f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        fromScreen = Math.max(fromScreen, 0);
952f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        toScreen = Math.min(toScreen, count - 1);
953f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
954f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        for (int i = fromScreen; i <= toScreen; i++) {
955f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            final CellLayout layout = (CellLayout) getChildAt(i);
956f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            layout.setChildrenDrawnWithCacheEnabled(true);
9579171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            layout.setChildrenDrawingCacheEnabled(true);
9589171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        }
9599171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    }
9609171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
9619c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka    void clearChildrenCache() {
9629c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        final int count = getChildCount();
9639c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        for (int i = 0; i < count; i++) {
9649c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            final CellLayout layout = (CellLayout) getChildAt(i);
9659c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            layout.setChildrenDrawnWithCacheEnabled(false);
9669c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        }
9679c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka    }
968760e5375f003accf04f789e90a919ed476d4c335Winson Chung
969760e5375f003accf04f789e90a919ed476d4c335Winson Chung    @Override
970760e5375f003accf04f789e90a919ed476d4c335Winson Chung    public boolean onTouchEvent(MotionEvent ev) {
971760e5375f003accf04f789e90a919ed476d4c335Winson Chung
972760e5375f003accf04f789e90a919ed476d4c335Winson Chung        if (mLauncher.isWorkspaceLocked()) {
9738d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung            return false; // We don't want the events.  Let them fall through to the all apps view.
9748d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung        }
9758d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung        if (mLauncher.isAllAppsVisible()) {
9768d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung            // Cancel any scrolling that is in progress.
9778d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung            if (!mScroller.isFinished()) {
9788d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung                mScroller.abortAnimation();
979b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung            }
9809171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            snapToScreen(mCurrentScreen);
9819171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            return false; // We don't want the events.  Let them fall through to the all apps view.
982e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka        }
983e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka
984e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka        if (mVelocityTracker == null) {
985e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            mVelocityTracker = VelocityTracker.obtain();
986e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka        }
987e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka        mVelocityTracker.addMovement(ev);
988f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung
9899171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        final int action = ev.getAction();
9909171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
9919171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        switch (action & MotionEvent.ACTION_MASK) {
9929171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        case MotionEvent.ACTION_DOWN:
9938d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung            /*
994b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung             * If being flinged and user touches, stop the fling. isFinished
9959171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung             * will be false if being flinged.
9969171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung             */
997e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            if (!mScroller.isFinished()) {
998e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka                mScroller.abortAnimation();
999e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            }
1000e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka
1001e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            // Remember where the motion event started
1002e0f5a61a1f105216b0067124bacac69194c0ef70Michael Jurka            mLastMotionX = ev.getX();
1003f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung            mActivePointerId = ev.getPointerId(0);
10049171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            if (mTouchState == TOUCH_STATE_SCROLLING) {
10059171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1);
10069171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            }
10079171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung            break;
10089171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        case MotionEvent.ACTION_MOVE:
10099c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            if (mTouchState == TOUCH_STATE_SCROLLING) {
10109c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka                // Scroll to follow the motion event
10119c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
10129c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka                final float x = ev.getX(pointerIndex);
10139171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                final float deltaX = mLastMotionX - x;
10149171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung                mLastMotionX = x;
1015f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
1016f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (deltaX < 0) {
1017f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    if (mTouchX > 0) {
1018f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                        mTouchX += Math.max(-mTouchX, deltaX);
10196b879f0a5885274a85333531e091283405d490ccAdam Lesinski                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
10206b879f0a5885274a85333531e091283405d490ccAdam Lesinski                        invalidate();
10216b879f0a5885274a85333531e091283405d490ccAdam Lesinski                    }
10226b879f0a5885274a85333531e091283405d490ccAdam Lesinski                } else if (deltaX > 0) {
10236b879f0a5885274a85333531e091283405d490ccAdam Lesinski                    final float availableToScroll = getChildAt(getChildCount() - 1).getRight() -
10246b879f0a5885274a85333531e091283405d490ccAdam Lesinski                            mTouchX - getWidth();
10256b879f0a5885274a85333531e091283405d490ccAdam Lesinski                    if (availableToScroll > 0) {
10266b879f0a5885274a85333531e091283405d490ccAdam Lesinski                        mTouchX += Math.min(availableToScroll, deltaX);
10276b879f0a5885274a85333531e091283405d490ccAdam Lesinski                        mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
10286b879f0a5885274a85333531e091283405d490ccAdam Lesinski                        invalidate();
10296b879f0a5885274a85333531e091283405d490ccAdam Lesinski                    }
10306b879f0a5885274a85333531e091283405d490ccAdam Lesinski                } else {
10316b879f0a5885274a85333531e091283405d490ccAdam Lesinski                    awakenScrollBars();
10326b879f0a5885274a85333531e091283405d490ccAdam Lesinski                }
10336b879f0a5885274a85333531e091283405d490ccAdam Lesinski            }
10346b879f0a5885274a85333531e091283405d490ccAdam Lesinski            break;
10356b879f0a5885274a85333531e091283405d490ccAdam Lesinski        case MotionEvent.ACTION_UP:
10366b879f0a5885274a85333531e091283405d490ccAdam Lesinski            if (mTouchState == TOUCH_STATE_SCROLLING) {
10376b879f0a5885274a85333531e091283405d490ccAdam Lesinski                final VelocityTracker velocityTracker = mVelocityTracker;
10386b879f0a5885274a85333531e091283405d490ccAdam Lesinski                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
10396b879f0a5885274a85333531e091283405d490ccAdam Lesinski                final int velocityX = (int) velocityTracker.getXVelocity(mActivePointerId);
10406b879f0a5885274a85333531e091283405d490ccAdam Lesinski
10416b879f0a5885274a85333531e091283405d490ccAdam Lesinski                final int screenWidth = getWidth();
10426b879f0a5885274a85333531e091283405d490ccAdam Lesinski                final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
10436b879f0a5885274a85333531e091283405d490ccAdam Lesinski                final float scrolledPos = (float) mScrollX / screenWidth;
104468d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
104568d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
104668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    // Fling hard enough to move left.
104768d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    // Don't fling across more than one screen at a time.
104868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    final int bound = scrolledPos < whichScreen ?
104968d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                            mCurrentScreen - 1 : mCurrentScreen;
105068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    snapToScreen(Math.min(whichScreen, bound), velocityX, true);
105168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) {
105268d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    // Fling hard enough to move right
105368d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    // Don't fling across more than one screen at a time.
105468d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    final int bound = scrolledPos > whichScreen ?
105568d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                            mCurrentScreen + 1 : mCurrentScreen;
105668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    snapToScreen(Math.max(whichScreen, bound), velocityX, true);
1057e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen                } else {
105868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    snapToScreen(whichScreen, 0, true);
105968d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                }
106068d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
106168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                if (mVelocityTracker != null) {
106268d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    mVelocityTracker.recycle();
106368d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                    mVelocityTracker = null;
106468d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen                }
106568d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen            }
106668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen            mTouchState = TOUCH_STATE_REST;
106768d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen            mActivePointerId = INVALID_POINTER;
1068f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            break;
1069f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        case MotionEvent.ACTION_CANCEL:
107021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            mTouchState = TOUCH_STATE_REST;
107168d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen            mActivePointerId = INVALID_POINTER;
107221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            break;
10731b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        case MotionEvent.ACTION_POINTER_UP:
10741b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            onSecondaryPointerUp(ev);
1075d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka            break;
107621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        }
107721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
1078f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        return true;
1079ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen    }
108021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
108121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    void snapToScreen(int whichScreen) {
1082f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        snapToScreen(whichScreen, 0, false);
1083e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen    }
1084e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen
1085e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen    private void snapToScreen(int whichScreen, int velocity, boolean settle) {
1086e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        // if (!mScroller.isFinished()) return;
1087e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen
1088e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
1089e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen
1090e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        clearVacantCache();
1091e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        enableChildrenCache(mCurrentScreen, whichScreen);
1092e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen
1093e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen        mNextScreen = whichScreen;
10941b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
109521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        if (mPreviousIndicator != null) {
10966b879f0a5885274a85333531e091283405d490ccAdam Lesinski            mPreviousIndicator.setLevel(mNextScreen);
10976b879f0a5885274a85333531e091283405d490ccAdam Lesinski            mNextIndicator.setLevel(mNextScreen);
109868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen        }
10991b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
1100f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        View focusedChild = getFocusedChild();
1101f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        if (focusedChild != null && whichScreen != mCurrentScreen &&
1102f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                focusedChild == getChildAt(mCurrentScreen)) {
1103f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            focusedChild.clearFocus();
110400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
110500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
11069c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        final int screenDelta = Math.max(1, Math.abs(whichScreen - mCurrentScreen));
1107956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        final int newX = whichScreen * getWidth();
11089c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        final int delta = newX - mScrollX;
11099c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        int duration = (screenDelta + 1) * 100;
11109c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka
11119c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        if (!mScroller.isFinished()) {
11129c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka            mScroller.abortAnimation();
111300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
111400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
111531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (settle) {
111628750fba6a2d141eb9a1e566718c17236030b815Michael Jurka            mScrollInterpolator.setDistance(screenDelta);
1117c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        } else {
1118c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka            mScrollInterpolator.disableSettle();
1119c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        }
11200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
1121aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        velocity = Math.abs(velocity);
112279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (velocity > 0) {
112379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            duration += (duration / (velocity / BASELINE_FLING_VELOCITY))
1124883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                    * FLING_VELOCITY_INFLUENCE;
1125696a67969d657d38eff33996633f08da0e21841fAdam Cohen        } else {
1126696a67969d657d38eff33996633f08da0e21841fAdam Cohen            duration += 100;
1127696a67969d657d38eff33996633f08da0e21841fAdam Cohen        }
1128696a67969d657d38eff33996633f08da0e21841fAdam Cohen
1129696a67969d657d38eff33996633f08da0e21841fAdam Cohen        awakenScrollBars(duration);
1130696a67969d657d38eff33996633f08da0e21841fAdam Cohen        mScroller.startScroll(mScrollX, 0, delta, 0, duration);
1131696a67969d657d38eff33996633f08da0e21841fAdam Cohen        invalidate();
1132696a67969d657d38eff33996633f08da0e21841fAdam Cohen    }
113379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
113479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void startDrag(CellLayout.CellInfo cellInfo) {
1135aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        View child = cellInfo.cell;
1136aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1137aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        // Make sure the drag was started by a long press as opposed to a long click.
11380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (!child.isInTouchMode()) {
1139aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            return;
114031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
114131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
114231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
11439171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        mDragInfo.screen = mCurrentScreen;
1144ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
1145c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka        CellLayout current = ((CellLayout) getChildAt(mCurrentScreen));
11469171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
11479c6fbed48783dacd9bc6b4ec5f2cc8e59ec7ee37Michael Jurka        current.onDragChild(child);
11488d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung        mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
11498d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung        invalidate();
115088127038178b3bbf0eb91103a31e682cc0615074Winson Chung    }
115188127038178b3bbf0eb91103a31e682cc0615074Winson Chung
115288127038178b3bbf0eb91103a31e682cc0615074Winson Chung    @Override
115388127038178b3bbf0eb91103a31e682cc0615074Winson Chung    protected Parcelable onSaveInstanceState() {
115488127038178b3bbf0eb91103a31e682cc0615074Winson Chung        final SavedState state = new SavedState(super.onSaveInstanceState());
115588127038178b3bbf0eb91103a31e682cc0615074Winson Chung        state.currentScreen = mCurrentScreen;
115688127038178b3bbf0eb91103a31e682cc0615074Winson Chung        return state;
1157760e5375f003accf04f789e90a919ed476d4c335Winson Chung    }
1158760e5375f003accf04f789e90a919ed476d4c335Winson Chung
1159760e5375f003accf04f789e90a919ed476d4c335Winson Chung    @Override
1160760e5375f003accf04f789e90a919ed476d4c335Winson Chung    protected void onRestoreInstanceState(Parcelable state) {
1161760e5375f003accf04f789e90a919ed476d4c335Winson Chung        SavedState savedState = (SavedState) state;
1162760e5375f003accf04f789e90a919ed476d4c335Winson Chung        super.onRestoreInstanceState(savedState.getSuperState());
116388127038178b3bbf0eb91103a31e682cc0615074Winson Chung        if (savedState.currentScreen != -1) {
116488127038178b3bbf0eb91103a31e682cc0615074Winson Chung            mCurrentScreen = savedState.currentScreen;
116588127038178b3bbf0eb91103a31e682cc0615074Winson Chung            Launcher.setScreen(mCurrentScreen);
1166ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung        }
116788127038178b3bbf0eb91103a31e682cc0615074Winson Chung    }
116888127038178b3bbf0eb91103a31e682cc0615074Winson Chung
116988127038178b3bbf0eb91103a31e682cc0615074Winson Chung    void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) {
1170ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung        addApplicationShortcut(info, cellInfo, false);
1171ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung    }
1172ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung
1173ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung    void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo,
1174ce93f7ebdb296846ba2f01b7eb3e69a3230f3025Winson Chung            boolean insertAtFirst) {
11758d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung        final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen);
11769171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        final int[] result = new int[2];
11779171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
11789171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        layout.cellToPoint(cellInfo.cellX, cellInfo.cellY, result);
11799171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung        onDropExternal(result[0], result[1], info, layout, insertAtFirst);
11809171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    }
11810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
1182c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
11830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            DragView dragView, Object dragInfo) {
11840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final CellLayout cellLayout = getCurrentDropLayout();
11850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (source != this) {
11860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            onDropExternal(x - xOffset, y - yOffset, dragInfo, cellLayout);
11870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
11882763be3150d429d338b9848286e9365b4052c100Michael Jurka            // Move internally
11892763be3150d429d338b9848286e9365b4052c100Michael Jurka            if (mDragInfo != null) {
11902763be3150d429d338b9848286e9365b4052c100Michael Jurka                final View cell = mDragInfo.cell;
11910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen;
11920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                if (index != mDragInfo.screen) {
11930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                    final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
1194cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                    originalCellLayout.removeView(cell);
11950207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    addInScreen(cell, index, mDragInfo.cellX, mDragInfo.cellY,
11960207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                            mDragInfo.spanX, mDragInfo.spanY);
11970207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                }
11980207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                mTargetCell = estimateDropCell(x - xOffset, y - yOffset,
11990207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                        mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout,
12000207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                        mTargetCell);
12010207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                cellLayout.onDropChild(cell);
12020207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
12030207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                // update the item's position after drop
12040207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final ItemInfo info = (ItemInfo) cell.getTag();
12050207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell
12060207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                        .getLayoutParams();
12070207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                lp.cellX = mTargetCell[0];
120833945b21544bc98381df17726a3537c292d8c985Michael Jurka                lp.cellY = mTargetCell[1];
12090207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
12100207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                LauncherModel.moveItemInDatabase(mLauncher, info,
12110207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                        LauncherSettings.Favorites.CONTAINER_DESKTOP, index,
121233945b21544bc98381df17726a3537c292d8c985Michael Jurka                        lp.cellX, lp.cellY);
12130207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            }
12140207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy        }
12150207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy    }
12160207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
12170207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy    public void onDragEnter(DragSource source, int x, int y, int xOffset,
12180207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            int yOffset, DragView dragView, Object dragInfo) {
1219cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        clearVacantCache();
12208ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy    }
12218ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
1222cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1223cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            DragView dragView, Object dragInfo) {
1224cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1225cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
1226cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1227cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
1228cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
122931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (dragInfo instanceof LauncherAppWidgetInfo) {
123031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
123131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
123231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (widgetInfo.spanX == -1) {
123331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Calculate the grid spans needed to fit this widget
1234678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato                int[] spans = currentLayout.rectToCell(widgetInfo.minWidth, widgetInfo.minHeight);
123531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                item.spanX = spans[0];
123631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                item.spanY = spans[1];
123731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
123831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
12390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (currentLayout != mDragTargetLayout) {
124031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragTargetLayout != null) {
124131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mDragTargetLayout.onDragComplete();
124231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
124331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mDragTargetLayout = currentLayout;
124431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
124531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1246c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy        // Find the top left corner of the item
1247678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        int originX = x - xOffset;
124831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int originY = y - yOffset;
12490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
125031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final View child = (mDragInfo == null) ? null : mDragInfo.cell;
12510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        currentLayout.visualizeDropLocation(child, originX, originY, item.spanX, item.spanY);
12520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
125331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
125431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDragExit(DragSource source, int x, int y, int xOffset,
125531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int yOffset, DragView dragView, Object dragInfo) {
125631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        clearVacantCache();
125731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (mDragTargetLayout != null) {
12587bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            mDragTargetLayout.onDragComplete();
12597bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            mDragTargetLayout = null;
126054dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka        }
126154dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka    }
12626b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato
12637bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    private void onDropExternal(int x, int y, Object dragInfo,
12647bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            CellLayout cellLayout) {
12657bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        onDropExternal(x, y, dragInfo, cellLayout, false);
12666b879f0a5885274a85333531e091283405d490ccAdam Lesinski    }
12677bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
12687bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    private void onDropExternal(int x, int y, Object dragInfo,
12697bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            CellLayout cellLayout, boolean insertAtFirst) {
12700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Drag from somewhere else
12710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ItemInfo info = (ItemInfo) dragInfo;
12720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
12730142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        View view = null;
12740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
12753a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        switch (info.itemType) {
1276aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
1277dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1278fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell            if (info.container == NO_ID && info instanceof ApplicationInfo) {
12790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                // Came from all apps -- make a copy
12800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                info = new ShortcutInfo((ApplicationInfo) info);
1281fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell            }
12820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            view = mLauncher.createShortcut(R.layout.application, cellLayout,
128331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    (ShortcutInfo) info);
128431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
128531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
128631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
128731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    (ViewGroup) getChildAt(mCurrentScreen),
128831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    ((UserFolderInfo) info));
128931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
1290dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
1291dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            cellLayout.setTagToCellInfoForPoint(x, y);
129231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mLauncher.addAppWidgetFromDrop(((LauncherAppWidgetInfo)dragInfo).providerName, cellLayout.getTag());
129331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
129431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
129531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalStateException("Unknown item type: "
129631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    + info.itemType);
129731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
129831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1299be9093426aec3a6d412811a12d2400e645613242Adam Cohen        // If the view is null, it has already been added.
1300be9093426aec3a6d412811a12d2400e645613242Adam Cohen        if (view == null) {
13016b879f0a5885274a85333531e091283405d490ccAdam Lesinski            cellLayout.onDragComplete();
1302be9093426aec3a6d412811a12d2400e645613242Adam Cohen        } else {
1303be9093426aec3a6d412811a12d2400e645613242Adam Cohen            mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
1304be9093426aec3a6d412811a12d2400e645613242Adam Cohen            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1305be9093426aec3a6d412811a12d2400e645613242Adam Cohen                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
13066b879f0a5885274a85333531e091283405d490ccAdam Lesinski            cellLayout.onDropChild(view);
1307be9093426aec3a6d412811a12d2400e645613242Adam Cohen            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
1308be9093426aec3a6d412811a12d2400e645613242Adam Cohen
1309be9093426aec3a6d412811a12d2400e645613242Adam Cohen            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
1310be9093426aec3a6d412811a12d2400e645613242Adam Cohen                    LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen,
1311be9093426aec3a6d412811a12d2400e645613242Adam Cohen                    lp.cellX, lp.cellY);
131231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
1313be9093426aec3a6d412811a12d2400e645613242Adam Cohen    }
1314be9093426aec3a6d412811a12d2400e645613242Adam Cohen
1315be9093426aec3a6d412811a12d2400e645613242Adam Cohen    /**
1316be9093426aec3a6d412811a12d2400e645613242Adam Cohen     * Return the current {@link CellLayout}, correctly picking the destination
1317be9093426aec3a6d412811a12d2400e645613242Adam Cohen     * screen while a scroll is in progress.
1318be9093426aec3a6d412811a12d2400e645613242Adam Cohen     */
1319be9093426aec3a6d412811a12d2400e645613242Adam Cohen    private CellLayout getCurrentDropLayout() {
1320be9093426aec3a6d412811a12d2400e645613242Adam Cohen        int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen;
1321be9093426aec3a6d412811a12d2400e645613242Adam Cohen        return (CellLayout) getChildAt(index);
13220142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
132331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1324aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    /**
1325ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka     * {@inheritDoc}
1326ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka     */
1327a7f801fc5b5715223e868ed599da69c5edf436eeMichael Jurka    public boolean acceptDrop(DragSource source, int x, int y,
1328ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
1329ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        final CellLayout layout = getCurrentDropLayout();
1330ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        final CellLayout.CellInfo cellInfo = mDragInfo;
1331ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        final int spanX = cellInfo == null ? 1 : cellInfo.spanX;
1332ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        final int spanY = cellInfo == null ? 1 : cellInfo.spanY;
1333ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka
1334ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        if (mVacantCache == null) {
1335ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            final View ignoreView = cellInfo == null ? null : cellInfo.cell;
1336ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            mVacantCache = layout.findAllVacantCells(null, ignoreView);
1337ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        }
1338ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka
1339ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        if (mVacantCache.findCellForSpan(mTempEstimate, spanX, spanY, false)) {
1340ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            return true;
1341ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka        } else {
1342ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            Toast.makeText(getContext(), getContext().getString(R.string.out_of_space), Toast.LENGTH_SHORT).show();
1343ce7e05fbe8abd5f25ec47e0e05b5cc76ceb39d2eMichael Jurka            return false;
13441d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown        }
13451d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown    }
13461d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown
13471d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown    /**
13481d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown     * {@inheritDoc}
13491d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown     */
13501d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown    public Rect estimateDropLocation(DragSource source, int x, int y,
13511d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown            int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle) {
13521d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown        final CellLayout layout = getCurrentDropLayout();
13531d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown
13541d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown        final CellLayout.CellInfo cellInfo = mDragInfo;
13551d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown        final int spanX = cellInfo == null ? 1 : cellInfo.spanX;
13561d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown        final int spanY = cellInfo == null ? 1 : cellInfo.spanY;
13571d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown        final View ignoreView = cellInfo == null ? null : cellInfo.cell;
13581d0867c8de6a889bccde9b7e768daef182a25e5cJeff Brown
135901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        final Rect location = recycle != null ? recycle : new Rect();
136001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
136101f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        // Find drop cell and convert into rectangle
136201f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        int[] dropCell = estimateDropCell(x - xOffset, y - yOffset, spanX,
1363a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                spanY, ignoreView, layout, mTempCell);
1364a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
1365a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        if (dropCell == null) {
1366a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            return null;
1367a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
1368a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
1369a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        layout.cellToPoint(dropCell[0], dropCell[1], mTempEstimate);
1370a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        location.left = mTempEstimate[0];
1371a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        location.top = mTempEstimate[1];
1372a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
1373a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        layout.cellToPoint(dropCell[0] + spanX, dropCell[1] + spanY, mTempEstimate);
1374a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        location.right = mTempEstimate[0];
1375af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        location.bottom = mTempEstimate[1];
1376af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka
1377af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        return location;
13789171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    }
13793c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka
13803c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka    /**
13813c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka     * Calculate the nearest cell where the given object would be dropped.
13823c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka     */
13833c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka    private int[] estimateDropCell(int pixelX, int pixelY,
13843c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
13853c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka
13863c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka        final int[] cellXY = mTempCell;
13873c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka        layout.estimateDropCell(pixelX, pixelY, spanX, spanY, cellXY);
13883c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka        layout.cellToPoint(cellXY[0], cellXY[1], mTempEstimate);
13893c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka
13903c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka        // Create vacant cell cache if none exists
13913c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka        if (mVacantCache == null) {
1392af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka            mVacantCache = layout.findAllVacantCells(null, ignoreView);
1393af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        }
13944c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka
13954c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka        // Find the best target drop location
13964c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka        return layout.findNearestVacantArea(mTempEstimate[0], mTempEstimate[1], spanX, spanY, mVacantCache, recycle);
13974c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka    }
13984c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka
13994c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka    void setLauncher(Launcher launcher) {
14004c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka        mLauncher = launcher;
14014c1085f8d94be2394dbce2866e94f60ac15ad109Michael Jurka    }
1402883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka
1403883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    public void setDragController(DragController dragController) {
1404883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        mDragController = dragController;
1405883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    }
1406883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka
1407883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    public void onDropCompleted(View target, boolean success) {
1408af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        clearVacantCache();
1409883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka
1410883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (success) {
14113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (target != this && mDragInfo != null) {
1412a997ac26664befbd0d5b172e36ef9e8b2c63b435Michael Jurka                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
1413d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka                cellLayout.removeView(mDragInfo.cell);
14140dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy                if (mDragInfo.cell instanceof DropTarget) {
1415d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
14163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                }
14171b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                // final Object tag = mDragInfo.cell.getTag();
14180dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy            }
14190dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        } else {
14200dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy            if (mDragInfo != null) {
14210dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
14220dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy                cellLayout.onDropAborted(mDragInfo.cell);
1423ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen            }
1424ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen        }
1425ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen
14261b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        mDragInfo = null;
14271b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    }
14280dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy
14290dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy    public void scrollLeft() {
14300dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        clearVacantCache();
14310dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        if (mScroller.isFinished()) {
14320dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy            if (mCurrentScreen > 0)
14330dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy                snapToScreen(mCurrentScreen - 1);
14340dfcf68b58bec1ac74f9b8700e3357f8e6d8b4a3Patrick Dubroy        } else {
14357247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy            if (mNextScreen > 0)
1436dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                snapToScreen(mNextScreen - 1);
1437213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
14380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
14390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
14400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void scrollRight() {
14410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        clearVacantCache();
14420142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mScroller.isFinished()) {
14430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (mCurrentScreen < getChildCount() - 1)
14440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                snapToScreen(mCurrentScreen + 1);
1445a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        } else {
1446dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            if (mNextScreen < getChildCount() - 1)
1447dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                snapToScreen(mNextScreen + 1);
1448a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
1449213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
1450df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung
1451742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    public int getScreenForView(View v) {
1452ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung        int result = -1;
1453ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung        if (v != null) {
14543e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ViewParent vp = v.getParent();
14553e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            int count = getChildCount();
1456f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen            for (int i = 0; i < count; i++) {
1457af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka                if (vp == getChildAt(i)) {
1458742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                    return i;
1459af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka                }
14603e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
14613e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
1462742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka        return result;
14636b879f0a5885274a85333531e091283405d490ccAdam Lesinski    }
1464af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka
1465742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    public Folder getFolderForTag(Object tag) {
1466b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung        int screenCount = getChildCount();
1467af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        for (int screen = 0; screen < screenCount; screen++) {
14683c38d561e6976ffc54eda61ed669870bbb8ec207Michael Jurka            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
1469213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka            int count = currentScreen.getChildCount();
1470dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            for (int i = 0; i < count; i++) {
1471f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen                View child = currentScreen.getChildAt(i);
1472f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
1473f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
1474f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen                    Folder f = (Folder) child;
1475f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen                    if (f.getInfo() == tag && f.getInfo().opened) {
1476f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen                        return f;
1477f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen                    }
1478dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                }
1479dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
1480dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
1481dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return null;
1482742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    }
1483a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
1484a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    public View getViewForTag(Object tag) {
1485a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int screenCount = getChildCount();
1486742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka        for (int screen = 0; screen < screenCount; screen++) {
1487742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
14883c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            int count = currentScreen.getChildCount();
14893c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            for (int i = 0; i < count; i++) {
14903c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                View child = currentScreen.getChildAt(i);
14913c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                if (child.getTag() == tag) {
1492f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen                    return child;
14933c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                }
1494742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka            }
1495742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka        }
1496742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka        return null;
1497742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    }
1498742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka
1499742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    /**
1500742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka     * @return True is long presses are still allowed for the current touch
1501742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka     */
1502742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    public boolean allowLongPress() {
1503742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka        return mAllowLongPress;
1504742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    }
1505742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka
1506742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka    /**
1507742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka     * Set true to allow long-press events to be triggered, usually checked by
1508742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka     * {@link Launcher} to accept or block dpad-initiated long-presses.
1509742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka     */
1510dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public void setAllowLongPress(boolean allowLongPress) {
1511f16e571330f030e445c4f7f63f55d093337ffd87Adam Cohen        mAllowLongPress = allowLongPress;
1512a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
1513f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
1514a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    void removeItems(final ArrayList<ApplicationInfo> apps) {
1515a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final int count = getChildCount();
1516a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final PackageManager manager = getContext().getPackageManager();
1517742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
1518742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka
1519abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka        final HashSet<String> packageNames = new HashSet<String>();
1520abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka        final int appCount = apps.size();
1521abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka        for (int i = 0; i < appCount; i++) {
1522abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka            packageNames.add(apps.get(i).componentName.getPackageName());
1523abded66084680bb31cc7ea403c88f44f79a3c884Michael Jurka        }
15243e5ad58a6885273a60f8eb77aa9aee965eecdb2cMichael Jurka
1525742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka        for (int i = 0; i < count; i++) {
1526742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka            final CellLayout layout = (CellLayout) getChildAt(i);
1527742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka
1528742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka            // Avoid ANRs by treating each screen separately
1529742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka            post(new Runnable() {
1530742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                public void run() {
1531742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
1532742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                    childrenToRemove.clear();
1533742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka
1534742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                    int childCount = layout.getChildCount();
1535742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                    for (int j = 0; j < childCount; j++) {
1536742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                        final View view = layout.getChildAt(j);
153779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                        Object tag = view.getTag();
1538742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka
1539742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                        if (tag instanceof ShortcutInfo) {
1540883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                            final ShortcutInfo info = (ShortcutInfo) tag;
1541883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                            final Intent intent = info.intent;
1542883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                            final ComponentName name = intent.getComponent();
15433e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
1544a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
15453e5ad58a6885273a60f8eb77aa9aee965eecdb2cMichael Jurka                                for (String packageName: packageNames) {
154679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                                    if (packageName.equals(name.getPackageName())) {
1547dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                                        // TODO: This should probably be done on a worker thread
1548742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1549dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                                        childrenToRemove.add(view);
1550ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                    }
1551ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                }
1552ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                            }
1553ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        } else if (tag instanceof UserFolderInfo) {
1554ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                            final UserFolderInfo info = (UserFolderInfo) tag;
1555ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                            final ArrayList<ShortcutInfo> contents = info.contents;
1556ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
1557ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                            final int contentsCount = contents.size();
1558ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                            boolean removedFromFolder = false;
1559ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka
1560ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                            for (int k = 0; k < contentsCount; k++) {
1561ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                final ShortcutInfo appInfo = contents.get(k);
1562ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                final Intent intent = appInfo.intent;
1563ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                final ComponentName name = intent.getComponent();
1564ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
1565ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
1566ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                    for (String packageName: packageNames) {
1567ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                        if (packageName.equals(name.getPackageName())) {
1568ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                            toRemove.add(appInfo);
1569ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                            // TODO: This should probably be done on a worker thread
1570ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                            LauncherModel.deleteItemFromDatabase(
1571ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                                    mLauncher, appInfo);
1572ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                            removedFromFolder = true;
1573ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                        }
1574ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                    }
1575ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                                }
1576ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                            }
1577ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
1578742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                            contents.removeAll(toRemove);
1579ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                            if (removedFromFolder) {
1580ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                final Folder folder = getOpenFolder();
1581ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                if (folder != null)
1582ca5b836e16d320f17057cd1a40a93c382e72501aMichael Jurka                                    folder.notifyDataSetChanged();
1583ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                            }
1584ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        } else if (tag instanceof LiveFolderInfo) {
1585742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                            final LiveFolderInfo info = (LiveFolderInfo) tag;
1586742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                            final Uri uri = info.uri;
1587742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                            final ProviderInfo providerInfo = manager.resolveContentProvider(
1588742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                    uri.getAuthority(), 0);
1589742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka
1590742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                            if (providerInfo != null) {
1591742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                for (String packageName: packageNames) {
1592742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                    if (packageName.equals(providerInfo.packageName)) {
1593742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                        // TODO: This should probably be done on a worker thread
1594742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1595742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                        childrenToRemove.add(view);
1596742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                    }
1597c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka                                }
1598c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka                            }
1599c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka                        } else if (tag instanceof LauncherAppWidgetInfo) {
1600c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
1601c4e772e4b3f21bde342e475ebc49b5b76b8f74e8Michael Jurka                            final AppWidgetProviderInfo provider =
1602742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                    widgets.getAppWidgetInfo(info.appWidgetId);
1603742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                            if (provider != null) {
1604742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                for (String packageName: packageNames) {
1605742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                    if (packageName.equals(provider.provider.getPackageName())) {
1606742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                        // TODO: This should probably be done on a worker thread
1607742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1608742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                        childrenToRemove.add(view);
1609742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                    }
1610742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                                }
1611742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                            }
1612742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                        }
1613742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                    }
1614742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka
1615742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                    childCount = childrenToRemove.size();
1616742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                    for (int j = 0; j < childCount; j++) {
1617742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                        View child = childrenToRemove.get(j);
1618742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                        layout.removeViewInLayout(child);
1619742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                        if (child instanceof DropTarget) {
1620742574b15b2b5298a2328443176f2890fb8ebe98Michael Jurka                            mDragController.removeDropTarget((DropTarget)child);
1621bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka                        }
16223c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                    }
1623ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka
1624ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                    if (childCount > 0) {
1625ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        layout.requestLayout();
1626ab1983f46ce0ee0c94ea1170d21a67eb4e3c7967Michael Jurka                        layout.invalidate();
16273c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                    }
1628dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                }
16298d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung            });
1630af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        }
16318d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung    }
16328d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung
1633760e5375f003accf04f789e90a919ed476d4c335Winson Chung    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
16348d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung        final PackageManager pm = mLauncher.getPackageManager();
1635dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
1636dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int count = getChildCount();
163761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        for (int i = 0; i < count; i++) {
163861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen            final CellLayout layout = (CellLayout) getChildAt(i);
163961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen            int childCount = layout.getChildCount();
164061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen            for (int j = 0; j < childCount; j++) {
164161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                final View view = layout.getChildAt(j);
164261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                Object tag = view.getTag();
164361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                if (tag instanceof ShortcutInfo) {
164461033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                    ShortcutInfo info = (ShortcutInfo)tag;
164561033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                    // We need to check for ACTION_MAIN otherwise getComponent() might
164661033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                    // return null for some shortcuts (for instance, for shortcuts to
164761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                    // web pages.)
164861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                    final Intent intent = info.intent;
164961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                    final ComponentName name = intent.getComponent();
1650eed565d5126cb40b2a7ecdf5f6e8ac7a7464007bAdam Cohen                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
1651eed565d5126cb40b2a7ecdf5f6e8ac7a7464007bAdam Cohen                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
165261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                        final int appCount = apps.size();
1653cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen                        for (int k = 0; k < appCount; k++) {
1654cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen                            ApplicationInfo app = apps.get(k);
1655cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen                            if (app.componentName.equals(name)) {
165661033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                                info.setIcon(mIconCache.getIcon(info.intent));
165761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
165861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
165961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                                        null, null);
166061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                                }
166161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                        }
166261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                    }
166361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen                }
1664cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen            }
166561033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        }
1666cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen    }
1667cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen
1668cbbaf9862aa160c5e397cb49b554de20981a35feAdam Cohen    void moveToDefaultScreen(boolean animate) {
166961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        if (animate) {
167061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen            snapToScreen(mDefaultScreen);
167161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        } else {
167261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen            setCurrentScreen(mDefaultScreen);
167361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        }
1674ea57348cc8f4647f6bc35a42cd45662ddb828b92Michael Jurka        getChildAt(mDefaultScreen).requestFocus();
167561033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen    }
167661033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen
167761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen    void setIndicators(Drawable previous, Drawable next) {
167861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        mPreviousIndicator = previous;
167961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        mNextIndicator = next;
168061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        previous.setLevel(mCurrentScreen);
168161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        next.setLevel(mCurrentScreen);
168261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen    }
168361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen
168461033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen    public static class SavedState extends BaseSavedState {
168561033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        int currentScreen = -1;
168661033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen
168761033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        SavedState(Parcelable superState) {
168861033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen            super(superState);
168961033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        }
169061033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen
169161033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        private SavedState(Parcel in) {
169261033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen            super(in);
169361033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen            currentScreen = in.readInt();
169461033d3d86fcae1f654f3fbfc9979d131e265d76Adam Cohen        }
16953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
1696af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        @Override
16973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        public void writeToParcel(Parcel out, int flags) {
16983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            super.writeToParcel(out, flags);
16993e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            out.writeInt(currentScreen);
1700af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        }
17013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
17023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        public static final Parcelable.Creator<SavedState> CREATOR =
17033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                new Parcelable.Creator<SavedState>() {
17043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            public SavedState createFromParcel(Parcel in) {
1705af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka                return new SavedState(in);
17063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
17073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
17083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            public SavedState[] newArray(int size) {
170933945b21544bc98381df17726a3537c292d8c985Michael Jurka                return new SavedState[size];
17103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
1711af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka        };
171233945b21544bc98381df17726a3537c292d8c985Michael Jurka    }
1713af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka}
1714af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka