Workspace.java revision 8e58e916061cbe2623697efac0924f2aa3753a92
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
19af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport com.android.launcher.R;
20495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell
210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.Animator;
22ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroyimport android.animation.Animator.AnimatorListener;
2318014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurkaimport android.animation.AnimatorListenerAdapter;
24b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.AnimatorSet;
250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.ObjectAnimator;
260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.PropertyValuesHolder;
278f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.app.WallpaperManager;
28629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetManager;
29629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
30495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.ComponentName;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent;
33495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.pm.PackageManager;
345c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.content.pm.ProviderInfo;
357247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.content.res.Resources;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.TypedArray;
374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Bitmap;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
39a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.graphics.Matrix;
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
414be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Region.Op;
42f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.graphics.drawable.Drawable;
435c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.net.Uri;
44956091ba7863bd72086275e61084864994dd6fa7Joe Onoratoimport android.os.IBinder;
45495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcelable;
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
47291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandlerimport android.util.Log;
4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
50f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
52af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.ArrayList;
53af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.HashSet;
54edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
5531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
58aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
5931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
61dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
62e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
633a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
65dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
66dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
67dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
68a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
69f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    // Y rotation to apply to the workspace screens
70f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final float WORKSPACE_ROTATION = 12.5f;
71a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
72a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // These are extra scale factors to apply to the mini home screens
73a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // so as to achieve the desired transform
74a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_0 = 0.97f;
75a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
76e54cec82a915c2bc8a7d719228c5d907f3fe14ecAdam Cohen    private static final float EXTRA_SCALE_FACTOR_2 = 1.08f;
77a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
78f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DELAY = 300;
79f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DURATION = 300;
80f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_IN_DURATION = 100;
81f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // These animators are used to fade the background
83472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeInAnimation;
84472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeOutAnimation;
85f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private float mBackgroundAlpha = 0;
86f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
878f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
88aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    private boolean mWaitingToShrinkToBottom = false;
9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    private boolean mPageMoving = false;
9421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
99aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
10070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
10170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
10270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
10370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1056569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
1066569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
1076569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
1086569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
1096569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
1110589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
11200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
113aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // These are temporary variables to prevent having to allocate a new object just to
1154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
11770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
1180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private float[] mTempOriginXY = new float[2];
119a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
1204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempTouchCoordinates = new float[2];
1214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempCellLayoutCenterCoordinates = new float[2];
122a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
1230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private Matrix mTempInverseMatrix = new Matrix();
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
125d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
126d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1288a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1298a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
130aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1311262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    // State variable that indicates whether the pages are small (ie when you're
132dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
133c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsSmall = false;
134c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsInUnshrinkAnimation = false;
135b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
1363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private enum ShrinkPosition {
1373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM_HIDDEN, SHRINK_TO_BOTTOM_VISIBLE };
1383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ShrinkPosition mShrunkenState;
139dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
1401262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    private boolean mInScrollArea = false;
1411262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1428e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
1434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap mDragOutline = null;
1448e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final Rect mTempRect = new Rect();
1458e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final int[] mTempXY = new int[2];
1464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1675f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
1685f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
1695f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFadeInAdjacentScreens = false;
1705f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1728f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
173aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
174aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
175aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
176d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
177d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
1780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
181d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
1820d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
1830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
1900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
1910589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
1920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
1930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
1940589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
1950589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
19631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
197472b281d5cb4f5660df981a6c912266b9f5703feChet Haase        mUnshrinkAnimationListener = new AnimatorListenerAdapter() {
198c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            public void onAnimationStart(Animator animation) {
199c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = true;
200c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            }
201b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationEnd(Animator animation) {
202c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = false;
203dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
204dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
2050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
2060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
20931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
210f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected int getScrollMode() {
211f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        if (LauncherApplication.isScreenXLarge()) {
212f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.QUINTIC_MODE;
213f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        } else {
214f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.OVERSHOOT_MODE;
215f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
216f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
217f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
218f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
21931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
22031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
22321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
22831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
23221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
24231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
24431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
26131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
2700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
271aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
272aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
273aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
274aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
281dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
282dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
284dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
2850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
2860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
2880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
289aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
290aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
291aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
292aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
29631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
3020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
3080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
3120142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
3130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
31731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
32031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
32631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
32731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
331aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
332aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
333aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
334aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
34031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
34131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
34231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
34331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @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     * @param insert When true, the child is inserted at the beginning of the children list.
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
349291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
350291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
351291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
35931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
36031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
36131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
364aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3656569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
366845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
367aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
368aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
369aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
3706569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
371aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
372aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
373aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
37431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
3750d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
37800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
379aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
38000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
38131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
38231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
383dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
384dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
385c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
3862b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
38796226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
38821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        } else if (!mPageMoving) {
38921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            if (v == getChildAt(mCurrentPage - 1)) {
39021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage - 1);
39121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
39221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            } else if (v == getChildAt(mCurrentPage + 1)) {
39321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage + 1);
39421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
39521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            }
396dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
397dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
3980e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
3990e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
4005f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4015f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
402c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4035f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4045f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4055f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4065f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
4075f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4085f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4095f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4105f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
411c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4125f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4135f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4145f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4155f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.onInterceptTouchEvent(ev);
4165f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4175f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4181adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    @Override
4191adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    protected void determineScrollingStart(MotionEvent ev) {
4201adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) super.determineScrollingStart(ev);
4211adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    }
4221adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka
4231262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageBeginMoving() {
4240142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
4250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
42616fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage, mNextPage);
4270142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4280142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
4290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
43016fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
43131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
432f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        showOutlines();
43321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = true;
43431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
43531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4361262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageEndMoving() {
43716fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        clearChildrenCache();
4381262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        // Hide the outlines, as long as we're not dragging
4391262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mDragController.dragging()) {
4401262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
4411262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
44221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = false;
4430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
4440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
4460142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
4470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
4480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
4500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
4510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
4520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
4590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
4600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
4610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4628f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
463798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
464798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
465798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
466798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
46786f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
46886f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
46986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
47086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
47186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
47286f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
47386f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
47486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
47586f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
476956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
4778f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
478aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
479f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void showOutlines() {
4803e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
4813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
4823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
483472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
484472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
4853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeInAnimation.start();
4863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
487f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
488f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
489f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void hideOutlines() {
4903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
4913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
4923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
493472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
494472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
4953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
4963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.start();
4973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
498f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
499f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
500f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void setBackgroundAlpha(float alpha) {
501f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        mBackgroundAlpha = alpha;
502f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
503f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
504f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            cl.setBackgroundAlpha(alpha);
505f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
506f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
507f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
508f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public float getBackgroundAlpha() {
509f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        return mBackgroundAlpha;
510f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
511f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
512f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
513f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected void screenScrolled(int screenCenter) {
51421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        final int halfScreenSize = getMeasuredWidth() / 2;
51521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
516f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            View v = getChildAt(i);
517f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            if (v != null) {
51821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int totalDistance = v.getMeasuredWidth() + mPageSpacing;
51921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int delta = screenCenter - (getChildOffset(i) -
52021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                        getRelativeChildOffset(i) + halfScreenSize);
521f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
52221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float scrollProgress = delta/(totalDistance*1.0f);
52321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.min(scrollProgress, 1.0f);
52421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.max(scrollProgress, -1.0f);
525f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
52621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float rotation = WORKSPACE_ROTATION * scrollProgress;
52721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                v.setRotationY(rotation);
528f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            }
529f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
530f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
531f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
53200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
53300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
534956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
53500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
53600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
53700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
53831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
53928750fba6a2d141eb9a1e566718c17236030b815Michael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
5400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
541aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
54279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
54379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
54479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mWaitingToShrinkToBottom) {
54579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            shrinkToBottom(false);
54679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = false;
54779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
54879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
549aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
550aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
551aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
5520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
553aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
55431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
55531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
55631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
558c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
5590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
5600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
5610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
5620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
5630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
5640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
5660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
5670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
5680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
56931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
57031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
57131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
57231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
57331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
574678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
57531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
57631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
57731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
57831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
5790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
58031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
58131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
58231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
58331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
58431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
58531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
586c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
587678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
58831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
5890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
59031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
5910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
5920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
59331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
59431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
59531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
59631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5987bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
5997bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
60054dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
60154dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
6026b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
6037bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
6047bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
6057bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
6067bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
6077bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
6087bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
6090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
6100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
6110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
6120142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
6130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
6143a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
615aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
616dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
617fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
6190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
620fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
62231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
62331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
62431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
62531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
62631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
62731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
62831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
629dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
630dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
63131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
63231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
63331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
63431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
63531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
63631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
63731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
6382bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
6392bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
6402bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
6412bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
6422bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
6433e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            setCurrentPage(mCurrentPage);
6447c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
64531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
64631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
64831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
649aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
65001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
65101f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
65201f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
65301f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
6546b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
6550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
65601f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
65701f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
65801f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
6590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
660213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
661213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
662213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
66379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
66479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
66579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
66679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
66779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mFirstLayout) {
66879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
66979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
67079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
67179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // to get our width so we can layout the mini-screen views correctly
67279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = true;
67379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        } else {
6743e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, animated);
67579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
676213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
677213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
678a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float getYScaleForScreen(int screen) {
679a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int x = Math.abs(screen - 2);
680a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
681a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // TODO: This should be generalized for use with arbitrary rotation angles.
682a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        switch(x) {
683a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 0: return EXTRA_SCALE_FACTOR_0;
684a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 1: return EXTRA_SCALE_FACTOR_1;
685a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 2: return EXTRA_SCALE_FACTOR_2;
686a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
687a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        return 1.0f;
688a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
689a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
690dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
6910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
692dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
6933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        mShrunkenState = shrinkPosition;
6943e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
6953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        // Stop any scrolling, move to the current page right away
6963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        setCurrentPage(mCurrentPage);
6973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
6983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
6995f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // we intercept and reject all touch events when we're small, so be sure to reset the state
7005f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mTouchState = TOUCH_STATE_REST;
7015f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mActivePointerId = INVALID_POINTER;
7025f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
7037247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
704dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
705213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
7060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
7080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
7090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
7100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
7120142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
713a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
714dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
715dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
716a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
717213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
718213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        float newY = getResources().getDimension(R.dimen.smallScreenVerticalMargin);
7193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float finalAlpha = 1.0f;
7203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float extraShrinkFactor = 1.0f;
7213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
7223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             newY = screenHeight - newY - scaledPageHeight;
7233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
7243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // We shrink and disappear to nothing in the case of all apps
7263e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // (which is when we shrink to the bottom)
7270142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
7283e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            finalAlpha = 0.0f;
7293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            extraShrinkFactor = 0.1f;
7300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
731b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            newY = screenHeight / 2 - scaledPageHeight / 2;
732b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            finalAlpha = 1.0f;
733b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_TOP) {
734b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            newY = screenHeight / 10;
735213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
736dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
737dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
738dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
739dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
740dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
7410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
742a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
743a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // We are going to scale about the center of the view, so we need to adjust the positions
744a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // of the views accordingly
745a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newX -= (pageWidth - scaledPageWidth) / 2.0f;
746a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newY -= (pageHeight - scaledPageHeight) / 2.0f;
747dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
748dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
749a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
750f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            float rotation = (-i + 2) * WORKSPACE_ROTATION;
751a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
752a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleY = getYScaleForScreen(i);
753a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
75479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
7557247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
756472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(cl,
757472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("x", newX),
758472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("y", newY),
759472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleX",
7603e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleX * extraShrinkFactor),
761472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleY",
7623e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor),
763472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha),
764472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("alpha", finalAlpha),
765472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("rotationY", rotation));
766472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.setDuration(duration);
767472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.start();
76879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
76979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
77079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
771f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                cl.setScaleX(SHRINK_FACTOR * rotationScaleX);
772f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                cl.setScaleY(SHRINK_FACTOR * rotationScaleY);
7735f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                cl.setBackgroundAlpha(1.0f);
7743e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                cl.setAlpha(finalAlpha);
775a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                cl.setRotationY(rotation);
77679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
777dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
778a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            newX += scaledPageWidth + extraScaledSpacing;
779dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
780dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
781dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
782dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
7833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
7853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
7863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
7873e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7883e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7893e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkPosition state, int spanX, int spanY) {
7903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, true, spanX, spanY);
7913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
7923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsHelper(
7943e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ShrinkPosition state, boolean isDragHappening, int spanX, int spanY) {
7953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        final int screenCount = getChildCount();
7963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        for (int i = 0; i < screenCount; i++) {
7973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
7983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7993e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            switch (state) {
8003e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_TOP:
8013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        boolean showDropHighlight = i == mCurrentPage;
8033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        cl.setAcceptsDrops(showDropHighlight);
8043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        break;
8053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // otherwise, fall through below and mark non-full screens as accepting drops
8073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_HIDDEN:
8083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_VISIBLE:
8093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // even if a drag isn't happening, we don't want to show a screen as
8113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // accepting drops if it doesn't have at least one free cell
8123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanX = 1;
8133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanY = 1;
8143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // the page accepts drops if we can find at least one empty spot
8163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
8173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    break;
8183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                default:
8193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                     throw new RuntimeException(
8203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkPosition");
8213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
8223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    /*
8263e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8273e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
8283e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
8293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8303e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * These methods mark the appropriate pages as accepting drops (which alters their visual
8313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * appearance) and, if the pages are hidden, makes them visible.
8323e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     */
8343e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemSpans(int spanX, int spanY) {
8353e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsDuringDrag(mShrunkenState, spanX, spanY);
8363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
8373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE, true);
8383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8413e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemMinSize(int minWidth, int minHeight) {
8423e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        int[] spanXY = CellLayout.rectToCell(getResources(), minWidth, minHeight, null);
8433e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        onDragStartedWithItemSpans(spanXY[0], spanXY[1]);
8443e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8453e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
8473e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // never dragged over
8483e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStopped() {
8493e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
8503e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
8513e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, true);
8523e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8533e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8543e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
855dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
8562b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
8570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
8584cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
8594cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
8604cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
8610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
8624cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
8634cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
8640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
8654cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
8664cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
86721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    @Override
86821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    protected boolean handlePagingClicks() {
86921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        return true;
87021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    }
87121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
8720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
873b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
8745f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
8755f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int delta = newX - mScrollX;
8764cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
877b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
878b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
879b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
880b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
881b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
8820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
883c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            unshrink();
884b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
885dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
886dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
8874cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
8884cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
8894cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
8904cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
8914cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
892b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
893c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mIsSmall = false;
894b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            AnimatorSet s = new AnimatorSet();
895b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
8964cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
8974cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
898b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
8997247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
9005f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
901f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                float rotation = 0.0f;
902f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
903f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (i < mCurrentPage) {
904f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = WORKSPACE_ROTATION;
905f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                } else if (i > mCurrentPage) {
906f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = -WORKSPACE_ROTATION;
907f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                }
908f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
9094cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
910472b281d5cb4f5660df981a6c912266b9f5703feChet Haase
9114cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    s.playTogether(
912472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationX", 0.0f).setDuration(duration),
913472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationY", 0.0f).setDuration(duration),
914472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleX", 1.0f).setDuration(duration),
915472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleY", 1.0f).setDuration(duration),
916472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "backgroundAlpha", 0.0f).setDuration(duration),
917472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "alpha", finalAlphaValue).setDuration(duration),
918472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "rotationY", rotation).setDuration(duration));
9194cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
9204cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
9214cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
9224cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
9234cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
9245f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setBackgroundAlpha(0.0f);
925f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setAlpha(finalAlphaValue);
926f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setRotationY(rotation);
9274cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
928b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
929c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            if (animated) {
930c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // If we call this when we're not animated, onAnimationEnd is never called on
931c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // the listener; make sure we only use the listener when we're actually animating
932c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                s.addListener(mUnshrinkAnimationListener);
933c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                s.start();
934c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            }
935dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
936dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
937dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
9384be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
9394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Draw the View v into the given Canvas.
9404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     *
9414be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param v the view to draw
9424be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param destCanvas the canvas to draw on
9434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param padding the horizontal and vertical padding to use when drawing
9444be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
9454be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private void drawDragView(View v, Canvas destCanvas, int padding) {
9464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Rect clipRect = mTempRect;
9474be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.getDrawingRect(clipRect);
9484be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9494be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // For a TextView, adjust the clip rect so that we don't include the text label
9504be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        if (v instanceof TextView) {
9514be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            final int iconHeight = ((TextView)v).getCompoundPaddingTop() - v.getPaddingTop();
9524be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            clipRect.bottom = clipRect.top + iconHeight;
9534be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        }
9544be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9554be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // Draw the View into the bitmap.
9564be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
9574be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // they set scrollX and scrollY to large values to achieve centered text
9584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9594be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.save();
9604be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
9614be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.clipRect(clipRect, Op.REPLACE);
9624be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.draw(destCanvas);
9634be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.restore();
9644be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
9654be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9664be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
9674be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
9684be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
9694be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
9704be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {
9714be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
9724be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
9734be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
9744be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9754be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
9764be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
9774be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
9784be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9794be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
9804be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
9814be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9824be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
9834be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to show when the given View is being dragged around.
9844be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
9854be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
9864be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
9874be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
9884be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
9894be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                mDragOutline.getWidth(), mDragOutline.getHeight(), Bitmap.Config.ARGB_8888);
9904be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9914be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
9924be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.drawBitmap(mDragOutline, 0, 0, null);
9934be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
9948e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
9954be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9964be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
9974be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
9984be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
99931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
100031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
1001aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
100231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
10037984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
100431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
100531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
1006aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
100731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
10080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
1009aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
101008ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        CellLayout current = getCurrentDropLayout();
101131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
101231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
10134be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10144be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.clearFocus();
10154be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.setPressed(false);
10164be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10174be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Canvas canvas = new Canvas();
10184be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10198e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        // We need to add extra padding to the bitmap to make room for the glow effect
10208e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
10218e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy
10224be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The outline is used to visualize where the item will land if dropped
10238e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mDragOutline = createDragOutline(child, canvas, bitmapPadding);
10244be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10254be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The drag bitmap follows the touch point around on the screen
10268e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final Bitmap b = createDragBitmap(child, canvas, bitmapPadding);
10274be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10284be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpWidth = b.getWidth();
10294be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpHeight = b.getHeight();
10304be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.getLocationOnScreen(mTempXY);
10314be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
10324be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
10334be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
10344be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                child.getTag(), DragController.DRAG_ACTION_MOVE, null);
10354be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        b.recycle();
103631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
103731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
10390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            boolean insertAtFirst, int intersectX, int intersectY) {
10400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
10410280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
104231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final int[] cellXY = new int[2];
10440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
10450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
10460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
10470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
10480280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellXY[0], cellXY[1]);
104931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
105031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1051ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    private void setPositionForDropAnimation(
1052ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            View dragView, int dragViewX, int dragViewY, View parent, View child) {
1053ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
1054ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1055ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // Based on the position of the drag view, find the top left of the original view
1056ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
1057ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
1058ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewX -= getResources().getInteger(R.integer.config_dragViewOffsetX);
1059ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewY -= getResources().getInteger(R.integer.config_dragViewOffsetY);
1060ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1061ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // Set its old pos (in the new parent's coordinates); the CellLayout will
1062ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // animate it from this position during the next layout pass
1063ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldX = viewX - (parent.getLeft() - mScrollX);
1064ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldY = viewY - (parent.getTop() - mScrollY);
1065ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    }
10660280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
106700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
106800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
1069ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1070ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originX = x - xOffset;
1071ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originY = y - yOffset;
1072ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1073d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout == null) {
1074ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // Cancel the drag if we're not over a screen at time of drop
1075ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            if (mDragInfo != null) {
1076ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                // Set its position so the parent can animate it back
1077ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                final View parent = getChildAt(mDragInfo.screen);
1078ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                setPositionForDropAnimation(dragView, originX, originY, parent, mDragInfo.cell);
1079ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            }
1080d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            return;
1081d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
1082ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1083c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
10840280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
10850280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
10860280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
1087d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
10880280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
10890280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
1090a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1091c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
109231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
1093d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
1094ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
109531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Move internally
1096ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            final View cell = mDragInfo.cell;
1097ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            mTargetCell = findNearestVacantArea(originX, originY,
1098ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
1099ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    mTargetCell);
1100ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1101ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            int screen = indexOfChild(mDragTargetLayout);
1102ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            if (screen != mDragInfo.screen) {
1103ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
1104ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                originalCellLayout.removeView(cell);
1105ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
1106ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                        mDragInfo.spanX, mDragInfo.spanY);
110731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1108ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            mDragTargetLayout.onDropChild(cell);
1109ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1110ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // update the item's position after drop
1111ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            final ItemInfo info = (ItemInfo) cell.getTag();
1112ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
1113ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
1114ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            lp.cellX = mTargetCell[0];
1115ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            lp.cellY = mTargetCell[1];
1116ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
1117ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
1118ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1119ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            LauncherModel.moveItemInDatabase(mLauncher, info,
1120ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1121ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    lp.cellX, lp.cellY);
1122ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1123ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // Prepare it to be animated into its new position
1124ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // This must be called after the view has been re-parented
1125ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            setPositionForDropAnimation(dragView, originX, originY, mDragTargetLayout, cell);
112631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
112731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
112831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1129aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
1130aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
113108ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        mDragTargetLayout = null; // Reset the drag state
113208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
1133d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall) {
113408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            mDragTargetLayout = getCurrentDropLayout();
113508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            mDragTargetLayout.onDragEnter(dragView);
1136d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            showOutlines();
1137d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
113831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
113931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
114018014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka    public DropTarget getDropTargetDelegate(DragSource source, int x, int y,
114118014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
11426569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1143c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1144d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
11450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return null;
11460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1147440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
1148440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
1149440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
1150440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
11516569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
1152440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
1153440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1154440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
1155440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
1156440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
1157440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
1158440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
1159440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
1160440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
1161440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
1162440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
1163440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
11640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointX += mScrollX - currentLayout.getLeft();
11650280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointY += mScrollY - currentLayout.getTop();
1166440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1167440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
1168440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
1169440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
1170440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
1171440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
1172440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
1173440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
1174440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
1175440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
1176440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
1177440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
1178440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
1179440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
11806569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
11814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
11824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
11844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
11854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
11874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy) {
11884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       mapPointFromSelfToChild(v, xy, null);
11894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
11904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
11924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
11944516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
11954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * if cachedInverseMatrix is not null, this method will just use that matrix instead of
1197d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka    * computing it itself; we use this to avoid redundant matrix inversions in
11984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * findMatchingPageForDragOver
11994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
12004516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
12014516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
12024516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       if (cachedInverseMatrix == null) {
12034516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           v.getMatrix().invert(mTempInverseMatrix);
12044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           cachedInverseMatrix = mTempInverseMatrix;
12054516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       }
12064516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] = xy[0] + mScrollX - v.getLeft();
12074516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] = xy[1] + mScrollY - v.getTop();
12084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       cachedInverseMatrix.mapPoints(xy);
12094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
12104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
12124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
12134516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from this CellLayout's coordinate space to
12144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * the parent View's coordinate space. The argument xy is modified with the return result.
12154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
12164516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
12174516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromChildToSelf(View v, float[] xy) {
12184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       v.getMatrix().mapPoints(xy);
12194516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] -= (mScrollX - v.getLeft());
12204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] -= (mScrollY - v.getTop());
12214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
12224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12234516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    static private float squaredDistance(float[] point1, float[] point2) {
12244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceX = point1[0] - point2[0];
12254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceY = point2[1] - point2[1];
12264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return distanceX * distanceX + distanceY * distanceY;
12270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
12280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
12294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
12304516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Returns true if the passed CellLayout cl overlaps with dragView
12324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12334516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
12344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    boolean overlaps(CellLayout cl, DragView dragView,
12354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
12364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the coordinates of the item being dragged to the CellLayout's coordinates
12374516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemTopLeft = mTempDragCoordinates;
12384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[0] = dragViewX + dragView.getScaledDragRegionXOffset();
12394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[1] = dragViewY + dragView.getScaledDragRegionYOffset();
12404516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
12414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getScaledDragRegionWidth();
12424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getScaledDragRegionHeight();
12434516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the dragged item's top left coordinates
12454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // to the CellLayout's local coordinates
12464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
12474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
12484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
12494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
12514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the dragged item's bottom right coordinates
12524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // to the CellLayout's local coordinates
12534516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
12544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
12554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
12564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
12584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float overlap = (overlapRegionRight - overlapRegionLeft) *
12594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                         (overlapRegionBottom - overlapRegionTop);
12604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (overlap > 0) {
12614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    return true;
12624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                }
12634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka             }
12644516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        }
12654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return false;
12664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    }
1267a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
12684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
12694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * This method returns the CellLayout that is currently being dragged to. In order to drag
12714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
12724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
12734516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12744516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Return null if no CellLayout is currently being dragged over
12754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
12774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private CellLayout findMatchingPageForDragOver(
12784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            DragView dragView, int originX, int originY, int offsetX, int offsetY) {
12794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which ones overlap
12804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // with the item being dragged and then choose the one that's closest to the touch point
1281a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
1282a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
12830280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float smallestDistSoFar = Float.MAX_VALUE;
12844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
1285a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
1286a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
1287a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
12884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            final float[] touchXy = mTempTouchCoordinates;
12894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[0] = originX + offsetX;
12904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[1] = originY + offsetY;
1291a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
12924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the touch coordinates to the CellLayout's local coordinates
12934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // If the touch point is within the bounds of the cell layout, we can return immediately
12940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cl.getMatrix().invert(mTempInverseMatrix);
12954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
12964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12974516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
12984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
12994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                return cl;
13004516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
13014516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13024516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
13034516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Get the center of the cell layout in screen coordinates
13044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
13054516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[0] = cl.getWidth()/2;
13064516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[1] = cl.getHeight()/2;
13074516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                mapPointFromChildToSelf(cl, cellLayoutCenter);
13084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[0] = originX + offsetX;
13104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[1] = originY + offsetY;
13114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Calculate the distance between the center of the CellLayout
13134516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // and the touch point
13144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float dist = squaredDistance(touchXy, cellLayoutCenter);
13154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13164516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (dist < smallestDistSoFar) {
13170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    smallestDistSoFar = dist;
1318a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
1319a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
13204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
1321a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1322a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
1323a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
1324a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1325440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1326440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
1327d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // When touch is inside the scroll area, skip dragOver actions for the current screen
1328d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mInScrollArea) {
1329d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            CellLayout layout;
1330d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originX = x - xOffset;
1331d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originY = y - yOffset;
1332d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mIsSmall || mIsInUnshrinkAnimation) {
1333d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = findMatchingPageForDragOver(
1334d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        dragView, originX, originY, xOffset, yOffset);
1335d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1336d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1337d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1338d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(false);
1339d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1340d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
1341d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1342d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(true);
1343d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1344d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1345d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            } else {
1346d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = getCurrentDropLayout();
1347d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1348d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                final ItemInfo item = (ItemInfo)dragInfo;
1349d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (dragInfo instanceof LauncherAppWidgetInfo) {
1350d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
1351d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1352d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (widgetInfo.spanX == -1) {
1353d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        // Calculate the grid spans needed to fit this widget
1354d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int[] spans = layout.rectToCell(
1355d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                widgetInfo.minWidth, widgetInfo.minHeight, null);
1356d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanX = spans[0];
1357d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanY = spans[1];
1358d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1359d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1360a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1361d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (source instanceof AllAppsPagedView) {
1362d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // This is a hack to fix the point used to determine which cell an icon from
1363d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // the all apps screen is over
1364d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (item != null && item.spanX == 1 && layout != null) {
1365d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
1366d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1367d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        originX += dragRegionLeft - dragView.getDragRegionLeft();
1368d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
1369d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            dragView.setDragRegion(dragView.getDragRegionLeft(),
1370d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionTop(),
1371d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    layout.getCellWidth(),
1372d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionHeight());
1373d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        }
1374d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1375a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
13761262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1377d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1378d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1379d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.onDragExit();
1380d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1381d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    layout.onDragEnter(dragView);
1382d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
13831262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                }
13846569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1385d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // only visualize the drop locations for moving icons within the home screen on
1386d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // tablet on phone, we also visualize icons dragged in from All Apps
1387d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if ((!LauncherApplication.isScreenXLarge() || source == this)
1388d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        && mDragTargetLayout != null) {
1389d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    final View child = (mDragInfo == null) ? null : mDragInfo.cell;
1390d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
1391d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
1392d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
1393d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            localOriginX, localOriginY, item.spanX, item.spanY);
1394d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
13951262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            }
1396976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
139731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
139831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1399aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
1400aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
14016569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
14020280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mDragTargetLayout.onDragExit();
14036569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
14041262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mIsPageMoving) {
14051262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
14061262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
140708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        clearAllHovers();
140831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
140931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1410aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1411aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
141231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
141331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1414aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
14152b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
14162b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
14172b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
14182b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
14192b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
14202b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
14212b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
14222b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
14232b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
14242b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
14250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
14262b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            onDropExternal(0, 0, dragInfo, cl, false);
14272b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
14282b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
14290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mLauncher.showOutOfSpaceMessage();
14302b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
14312b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
14322b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
14330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    // Drag from somewhere else
14344be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // NOTE: This can also be called when we are outside of a drag event, when we want
14354be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // to add an item to one of the workspace screens.
1436aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1437aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
14380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int screen = indexOfChild(cellLayout);
14390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (dragInfo instanceof PendingAddItemInfo) {
14400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
14410280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // When dragging and dropping from customization tray, we deal with creating
14420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // widgets/shortcuts/folders in a slightly different way
14430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            int[] touchXY = new int[2];
14440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[0] = x;
14450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[1] = y;
14460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            switch (info.itemType) {
14470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
14480280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addAppWidgetFromDrop(info.componentName, screen, touchXY);
14490280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
14500280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
14510280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
14520280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
14530280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
14540280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
14550280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
14560280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                default:
14570280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    throw new IllegalStateException("Unknown item type: " + info.itemType);
14580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
14590280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
146018014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
14610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return;
14620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
14630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
14640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        // This is for other drag/drop cases, like dragging from All Apps
146531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
146631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1467af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
146831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
146931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
147031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
147131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1472e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
147331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1474aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
147531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1476aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1477aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
147831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
147931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
148031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
14810280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    cellLayout, ((UserFolderInfo) info));
1482af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
148331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
14840280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            throw new IllegalStateException("Unknown item type: " + info.itemType);
148531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
148631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14876569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
14886569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
14890280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
14906569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
14917ded67cd64153cd41bb133a6aab11b3254b4a5d9Michael Jurka            mTargetCell = findNearestVacantArea(x, y, 1, 1, null, cellLayout, mTargetCell);
1492aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1493aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1494aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
149518014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
14966569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
149731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1498af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
14990280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1500aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1501af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
150231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1503aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
150470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
150570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
150670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
150770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
150870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
1509d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // if we're currently small, use findMatchingPageForDragOver instead
1510d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mIsSmall) return null;
15110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
151270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
151370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
151431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
151570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
15160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * Return the current CellInfo describing our current drag; this method exists
15170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * so that Launcher can sync this object with the correct info when the activity is created/
15180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * destroyed
15190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     *
15200280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     */
15210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public CellLayout.CellInfo getDragInfo() {
15220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return mDragInfo;
15230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
15240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
15250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    /**
152670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * {@inheritDoc}
152770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
152870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    public boolean acceptDrop(DragSource source, int x, int y,
152900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
1530d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout == null) {
1531d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // cancel the drag if we're not over a screen at time of drop
1532d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            return false;
15330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1534d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1535c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final CellLayout.CellInfo dragCellInfo = mDragInfo;
1536c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1537c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
15384c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1539c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
15404c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1541d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
15420e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return true;
15430e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        } else {
15440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mLauncher.showOutOfSpaceMessage();
15450e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return false;
15460e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        }
154770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1548aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
154970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
155070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
155170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
15526a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka    private int[] findNearestVacantArea(int pixelX, int pixelY,
155370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
15546569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
15555f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
15565f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelY = pixelY - (layout.getTop() - mScrollY);
15576569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
155870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
15590280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return layout.findNearestVacantArea(
1560fc9f07d42511231a26fa182c32e2efaa0f41d478Michael Jurka                localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
156170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1562aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
15638f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
15648f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
15658f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
15668f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
15670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
15688f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
15698f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
157031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
157131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
157231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
157331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
157400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
157500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
157631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
157731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
157831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1579aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
158031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
158131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
158231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
158300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
158400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
158500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1586aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
158731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1588ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
1589ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            ((CellLayout) getChildAt(mDragInfo.screen)).onDropAborted(mDragInfo.cell);
159031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
159131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15924be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragOutline = null;
159331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
159431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
159531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
15970280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return true;
15980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
15990280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
16000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
16010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
16020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
16030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
16040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
16050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
16060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
160731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
1608c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
16090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
161031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
161131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
161231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
161431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
1615c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
16160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
161731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
161831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1619138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
16201262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
16211262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onEnterScrollArea(int direction) {
1622d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
1623d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = true;
1624d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            final int screen = getCurrentPage() + ((direction == DragController.SCROLL_LEFT) ? -1 : 1);
1625d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (0 <= screen && screen < getChildCount()) {
1626d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                ((CellLayout) getChildAt(screen)).setHover(true);
1627d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
16281262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1629d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mDragTargetLayout != null) {
1630d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout.onDragExit();
1631d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout = null;
1632d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
16331262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
16341262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
16351262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
163608ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    private void clearAllHovers() {
163708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        final int childCount = getChildCount();
163808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        for (int i = 0; i < childCount; i++) {
163908ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            ((CellLayout) getChildAt(i)).setHover(false);
164008ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        }
164108ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    }
164208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
16431262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
16441262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onExitScrollArea() {
1645d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mInScrollArea) {
1646d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = false;
164708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            clearAllHovers();
16481262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
16491262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
16501262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
165131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1652dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
165331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
165431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
165531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
165631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
165731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
165831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
165931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
166031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
1661aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
166231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
166331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
166431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
166531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
166631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
166731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
166831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
166931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
167031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
167131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
167231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
167331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
167431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
167531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
167631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
167731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
167831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
167931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
168031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
168131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
168231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
168331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
168431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
168531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
168664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
1687dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
16885c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
1689629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
1690574d20ec84551370987dde530c27ec493bdef564Romain Guy
169164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
169264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
169364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
169464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
169564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
169664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
1697dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
169831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1699629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1700629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
1701629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
1702629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
1703629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
1704629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
1705aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1706629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
1707629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1708629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
1709629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
1710aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
17110589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
17120589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
1713629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
1714629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
1715aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
171664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
171764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
171864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
171964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
172064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
172164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
172264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1723629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1724629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
1725629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
17260589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
17270589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
1728629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
1729629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
1730aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1731629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
17320589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
1733629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
1734629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
1735aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
173664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
173764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
173864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
173964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
174073013bf94f49ffbacba2b8300f6a2dd4eeebbd13Brad Fitzpatrick                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
174164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
174264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
174364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
1744629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
1745629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1746aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1747629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
1748629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
1749629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
1750aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
1751aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
1752629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1753629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
1754629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
1755629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
1756629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
1757629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
1758629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1759f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
176064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
176164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
176264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1763aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
176464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
176564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1766629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1767629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
1768629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
1769629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
1770629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
1771e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
177264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
177364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
177464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1775aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
177664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
177764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1778629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1779574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
1780574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1781aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1782629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
1783629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1784629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
1785629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
1786629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
1787629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
1788629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
1789574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1790aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1791629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
1792629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
1793629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
17945c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
179531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
1796629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
179731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
179831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1799f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
180064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
1801dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
1802dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
1803f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1804f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
1805f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
1806f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
1807f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
18080589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
18090589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
1810f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
1811f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
1812f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
1813f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
1814f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
1815f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
181664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
181764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
1818aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
181964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
182064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
182164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
182264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
182364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
182464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
182564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
182664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
1827f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
1828f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
1829f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
1830f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
1831f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
1832f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
183314f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
1834c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1835c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
1836c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        } else if (animate) {
1837c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            snapToPage(mDefaultPage);
1838c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
18390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
1840c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
18410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
184231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
184331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18448a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
18458a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
18468a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
18470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
18480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
18498a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
18508a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
18510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
18520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
18530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
185431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
18560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
185731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
185931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
1860