Workspace.java revision 3e7c7634531302271270c8cf418abc959d621cbc
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;
22de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroyimport android.animation.Animator.AnimatorListener;
23b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.AnimatorSet;
240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.ObjectAnimator;
250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.PropertyValuesHolder;
268f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.app.WallpaperManager;
27629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetManager;
28629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
29495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.ComponentName;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent;
32495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.pm.PackageManager;
335c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.content.pm.ProviderInfo;
347247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.content.res.Resources;
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.TypedArray;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
37a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.graphics.Matrix;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
39f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.graphics.drawable.Drawable;
405c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.net.Uri;
41956091ba7863bd72086275e61084864994dd6fa7Joe Onoratoimport android.os.IBinder;
42495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcelable;
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
44291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandlerimport android.util.Log;
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
47f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
49af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.ArrayList;
50af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.HashSet;
51edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
5231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
55aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
58dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
59e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
603a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
62dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
63dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
64dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
65a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
66f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    // Y rotation to apply to the workspace screens
67f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final float WORKSPACE_ROTATION = 12.5f;
68a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
69a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // These are extra scale factors to apply to the mini home screens
70a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // so as to achieve the desired transform
71a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_0 = 0.97f;
72a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
73e54cec82a915c2bc8a7d719228c5d907f3fe14ecAdam Cohen    private static final float EXTRA_SCALE_FACTOR_2 = 1.08f;
74a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
75f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DELAY = 300;
76f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DURATION = 300;
77f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_IN_DURATION = 100;
78f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
793e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // These animators are used to fade the background
803e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ObjectAnimator<Float> mBackgroundFadeInAnimation;
813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ObjectAnimator<Float> mBackgroundFadeOutAnimation;
82f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private float mBackgroundAlpha = 0;
83f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
848f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
85aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
8731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
8879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    private boolean mWaitingToShrinkToBottom = false;
8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    private boolean mPageMoving = false;
9121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
9431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
96aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
9770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
9870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
9970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
10070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1026569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
1036569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
1046569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
1056569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
1066569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
1080589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
10900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
110aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // These are temporary variables to prevent having to allocate a new object just to
1124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
11470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
1150280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private float[] mTempOriginXY = new float[2];
116a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
1174516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempTouchCoordinates = new float[2];
1184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempCellLayoutCenterCoordinates = new float[2];
119a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
1200280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private Matrix mTempInverseMatrix = new Matrix();
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
122d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
123d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1258a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1268a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
127aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1281262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    // State variable that indicates whether the pages are small (ie when you're
129dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
130c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsSmall = false;
131c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsInUnshrinkAnimation = false;
132b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
1333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private enum ShrinkPosition {
1343e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM_HIDDEN, SHRINK_TO_BOTTOM_VISIBLE };
1353e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ShrinkPosition mShrunkenState;
136dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
1371262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    private boolean mInScrollArea = false;
1381262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
14531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1595f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
1605f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
1615f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFadeInAdjacentScreens = false;
1625f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1648f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
165aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
166aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
167aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
168d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
169d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
1700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
173d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
1740d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
1750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
17731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
1820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
1830589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
1840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
1850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
1860589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
1870589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
189b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase        mUnshrinkAnimationListener = new AnimatorListener() {
190c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            public void onAnimationStart(Animator animation) {
191c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = true;
192c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            }
193b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationEnd(Animator animation) {
194c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = false;
195dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
196b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationCancel(Animator animation) {}
197b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationRepeat(Animator animation) {}
198dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
1990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
2000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
20231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
20331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
204f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected int getScrollMode() {
205f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        if (LauncherApplication.isScreenXLarge()) {
206f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.QUINTIC_MODE;
207f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        } else {
208f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.OVERSHOOT_MODE;
209f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
210f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
211f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
212f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
21331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
21431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
21531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
21721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
21831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
21931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
22621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
22731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
22831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
23521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
24231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
25031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
2640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
265aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
266aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
267aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
268aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
275dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
276dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
278dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
2790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
2800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
2820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
283aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
284aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
285aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
286aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
29031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
29131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
2960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
30131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
3020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
3060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
3070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
31131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
31731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
32031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
325aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
326aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
327aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
328aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
33131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
34031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
34131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
34231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
343291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
344291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
345291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
35031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
358aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3596569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
360845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
361aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
362aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
363aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
3646569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
365aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
366aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
367aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
3690d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
37031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
37131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
37200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
373aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
37400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
37531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
377dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
378dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
379c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
3802b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
38196226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
38221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        } else if (!mPageMoving) {
38321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            if (v == getChildAt(mCurrentPage - 1)) {
38421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage - 1);
38521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
38621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            } else if (v == getChildAt(mCurrentPage + 1)) {
38721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage + 1);
38821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
38921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            }
390dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
391dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
3920e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
3930e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
3945f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
3955f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
396c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
3975f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
3985f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
3995f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4005f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
4015f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4025f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4035f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4045f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
405c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4065f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4075f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4085f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4095f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.onInterceptTouchEvent(ev);
4105f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4115f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4121262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageBeginMoving() {
4130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
4140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
41516fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage, mNextPage);
4160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
4180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
41916fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
42031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
421f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        showOutlines();
42221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = true;
42331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
42431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4251262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageEndMoving() {
42616fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        clearChildrenCache();
4271262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        // Hide the outlines, as long as we're not dragging
4281262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mDragController.dragging()) {
4291262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
4301262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
43121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = false;
4320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
4330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4340142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
4350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
4360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
4370142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
4390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
4400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
4410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4420142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4460142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
4480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
4490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
4500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4518f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
452798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
453798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
454798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
455798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
45686f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
45786f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
45886f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
45986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
46086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
46186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
46286f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
46386f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
46486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
465956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
4668f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
467aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
468f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void showOutlines() {
4693e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
4703e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
4713e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
4723e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeInAnimation = new ObjectAnimator<Float>(BACKGROUND_FADE_IN_DURATION,
4733e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    this, new PropertyValuesHolder<Float>("backgroundAlpha", 1.0f));
4743e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeInAnimation.start();
4753e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
476f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
477f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
478f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void hideOutlines() {
4793e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
4803e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
4813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
4823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation = new ObjectAnimator<Float>(BACKGROUND_FADE_OUT_DURATION,
4833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    this, new PropertyValuesHolder<Float>("backgroundAlpha", 0.0f));
4843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
4853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.start();
4863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
487f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
488f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
489f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void setBackgroundAlpha(float alpha) {
490f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        mBackgroundAlpha = alpha;
491f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
492f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
493f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            cl.setBackgroundAlpha(alpha);
494f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
495f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
496f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
497f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public float getBackgroundAlpha() {
498f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        return mBackgroundAlpha;
499f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
500f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
501f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
502f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected void screenScrolled(int screenCenter) {
50321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        final int halfScreenSize = getMeasuredWidth() / 2;
50421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
505f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            View v = getChildAt(i);
506f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            if (v != null) {
50721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int totalDistance = v.getMeasuredWidth() + mPageSpacing;
50821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int delta = screenCenter - (getChildOffset(i) -
50921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                        getRelativeChildOffset(i) + halfScreenSize);
510f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
51121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float scrollProgress = delta/(totalDistance*1.0f);
51221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.min(scrollProgress, 1.0f);
51321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.max(scrollProgress, -1.0f);
514f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
51521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float rotation = WORKSPACE_ROTATION * scrollProgress;
51621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                v.setRotationY(rotation);
517f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            }
518f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
519f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
520f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
52100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
52200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
523956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
52400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
52500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
52600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
52731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
52828750fba6a2d141eb9a1e566718c17236030b815Michael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
5290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
530aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
53179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
53279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
53379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mWaitingToShrinkToBottom) {
53479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            shrinkToBottom(false);
53579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = false;
53679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
53779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
538aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
539aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
540aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
5410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
542aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
54331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
54431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
54531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5460142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
547c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
5480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
5490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
5500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
5510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
5520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
5530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
5550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
5560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
5570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
55831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
55931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
56031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
56131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
56231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
563678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
56431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
56531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
56631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
56731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
5680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
56931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
57031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
57131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
57231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
57331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
57431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
575c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
576678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
57731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
5780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
57931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
5800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
5810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
58231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
58331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
58431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
58531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
58631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5877bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
5887bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
58954dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
59054dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
5916b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
5927bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
5937bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
5947bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
5957bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
5967bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
5977bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
5980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
5990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
6000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
6010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
6020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
6033a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
604aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
605dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
606fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
6080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
609fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
61131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
61231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
61331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
61431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
61531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
61631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
61731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
618dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
619dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
62031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
62131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
62231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
62331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
62431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
62531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
62631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
6272bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
6282bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
6292bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
6302bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
6312bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
6323e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            setCurrentPage(mCurrentPage);
6337c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
63431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
63531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
63731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
638aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
63901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
64001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
64101f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
64201f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
6436b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
6440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
64501f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
64601f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
64701f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
6480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
649213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
650213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
651213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
65279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
65379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
65479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
65579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
65679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mFirstLayout) {
65779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
65879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
65979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
66079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // to get our width so we can layout the mini-screen views correctly
66179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = true;
66279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        } else {
6633e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, animated);
66479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
665213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
666213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
667a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float getYScaleForScreen(int screen) {
668a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int x = Math.abs(screen - 2);
669a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
670a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // TODO: This should be generalized for use with arbitrary rotation angles.
671a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        switch(x) {
672a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 0: return EXTRA_SCALE_FACTOR_0;
673a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 1: return EXTRA_SCALE_FACTOR_1;
674a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 2: return EXTRA_SCALE_FACTOR_2;
675a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
676a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        return 1.0f;
677a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
678a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
679dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
6800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
681dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
6823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        mShrunkenState = shrinkPosition;
6833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
6843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        // Stop any scrolling, move to the current page right away
6853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        setCurrentPage(mCurrentPage);
6863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
6873e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
6885f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // we intercept and reject all touch events when we're small, so be sure to reset the state
6895f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mTouchState = TOUCH_STATE_REST;
6905f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mActivePointerId = INVALID_POINTER;
6915f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
6927247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
693dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
694213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
6950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
6970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
6980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
6990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
7010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
702a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
703dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
704dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
705a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
706213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
707213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        float newY = getResources().getDimension(R.dimen.smallScreenVerticalMargin);
7083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float finalAlpha = 1.0f;
7093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float extraShrinkFactor = 1.0f;
7103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
7113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             newY = screenHeight - newY - scaledPageHeight;
7123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
7133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // We shrink and disappear to nothing in the case of all apps
7153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // (which is when we shrink to the bottom)
7160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
7173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            finalAlpha = 0.0f;
7183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            extraShrinkFactor = 0.1f;
7190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
7203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             newY = screenHeight / 2 - scaledPageHeight / 2;
7213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             finalAlpha = 1.0f;
722213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
723dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
724dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
725dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
726dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
727dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
7280142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
729a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
730a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // We are going to scale about the center of the view, so we need to adjust the positions
731a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // of the views accordingly
732a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newX -= (pageWidth - scaledPageWidth) / 2.0f;
733a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newY -= (pageHeight - scaledPageHeight) / 2.0f;
734dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
735dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
736a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
737f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            float rotation = (-i + 2) * WORKSPACE_ROTATION;
738a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
739a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleY = getYScaleForScreen(i);
740a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
74179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
7427247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
7435f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                new ObjectAnimator<Float>(duration, cl,
7445f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                        new PropertyValuesHolder<Float>("x", newX),
7455f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                        new PropertyValuesHolder<Float>("y", newY),
7463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        new PropertyValuesHolder<Float>("scaleX",
7473e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleX * extraShrinkFactor),
7483e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        new PropertyValuesHolder<Float>("scaleY",
7493e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor),
7503e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        new PropertyValuesHolder<Float>("backgroundAlpha", finalAlpha),
7513e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        new PropertyValuesHolder<Float>("alpha", finalAlpha),
7525f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                        new PropertyValuesHolder<Float>("rotationY", rotation)).start();
75379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
75479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
75579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
756f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                cl.setScaleX(SHRINK_FACTOR * rotationScaleX);
757f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                cl.setScaleY(SHRINK_FACTOR * rotationScaleY);
7585f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                cl.setBackgroundAlpha(1.0f);
7593e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                cl.setAlpha(finalAlpha);
760a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                cl.setRotationY(rotation);
76179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
762dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
763a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            newX += scaledPageWidth + extraScaledSpacing;
764dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
765dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
766dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
767dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
7683e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7693e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
7703e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
7713e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
7723e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7733e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7743e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkPosition state, int spanX, int spanY) {
7753e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, true, spanX, spanY);
7763e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
7773e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7783e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsHelper(
7793e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ShrinkPosition state, boolean isDragHappening, int spanX, int spanY) {
7803e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        final int screenCount = getChildCount();
7813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        for (int i = 0; i < screenCount; i++) {
7823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
7833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            switch (state) {
7853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_TOP:
7863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
7873e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        boolean showDropHighlight = i == mCurrentPage;
7883e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        cl.setAcceptsDrops(showDropHighlight);
7893e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        break;
7903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
7913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // otherwise, fall through below and mark non-full screens as accepting drops
7923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_HIDDEN:
7933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_VISIBLE:
7943e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
7953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // even if a drag isn't happening, we don't want to show a screen as
7963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // accepting drops if it doesn't have at least one free cell
7973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanX = 1;
7983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanY = 1;
7993e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8003e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // the page accepts drops if we can find at least one empty spot
8013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
8023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    break;
8033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                default:
8043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                     throw new RuntimeException(
8053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkPosition");
8063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
8073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    /*
8113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
8133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
8143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * These methods mark the appropriate pages as accepting drops (which alters their visual
8163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * appearance) and, if the pages are hidden, makes them visible.
8173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     */
8193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemSpans(int spanX, int spanY) {
8203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsDuringDrag(mShrunkenState, spanX, spanY);
8213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
8223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE, true);
8233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8263e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemMinSize(int minWidth, int minHeight) {
8273e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        int[] spanXY = CellLayout.rectToCell(getResources(), minWidth, minHeight, null);
8283e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        onDragStartedWithItemSpans(spanXY[0], spanXY[1]);
8293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8303e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
8323e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // never dragged over
8333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStopped() {
8343e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
8353e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
8363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, true);
8373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
840dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
8412b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
8420142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
8434cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
8444cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
8454cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
8460142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
8474cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
8484cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
8490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
8504cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
8514cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
85221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    @Override
85321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    protected boolean handlePagingClicks() {
85421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        return true;
85521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    }
85621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
8570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
858b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
8595f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
8605f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int delta = newX - mScrollX;
8614cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
862b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
863b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
864b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
865b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
866b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
8670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
868c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            unshrink();
869b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
870dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
871dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
8724cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
8734cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
8744cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
8754cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
8764cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
877b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
878c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mIsSmall = false;
879b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            AnimatorSet s = new AnimatorSet();
880b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
8814cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
8824cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
883b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
8847247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
8855f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
886f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                float rotation = 0.0f;
887f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
888f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (i < mCurrentPage) {
889f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = WORKSPACE_ROTATION;
890f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                } else if (i > mCurrentPage) {
891f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = -WORKSPACE_ROTATION;
892f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                }
893f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
8944cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
8954cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    s.playTogether(
896b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "translationX", 0.0f),
897b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "translationY", 0.0f),
898b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "scaleX", 1.0f),
899b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "scaleY", 1.0f),
9005f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                            new ObjectAnimator<Float>(duration, cl, "backgroundAlpha", 0.0f),
9015f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                            new ObjectAnimator<Float>(duration, cl, "alpha", finalAlphaValue),
902f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                            new ObjectAnimator<Float>(duration, cl, "rotationY", rotation));
9034cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
9044cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
9054cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
9064cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
9074cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
9085f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setBackgroundAlpha(0.0f);
909f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setAlpha(finalAlphaValue);
910f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setRotationY(rotation);
9114cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
912b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
913b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            s.addListener(mUnshrinkAnimationListener);
914b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            s.start();
915dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
916dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
917dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
91831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
91931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
920aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
92131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
9227984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
92331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
92431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
925aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
92631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
9270142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
928aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
9290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout current = ((CellLayout) getChildAt(mCurrentPage));
93031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
93131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
93200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
933de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        current.onDragEnter(child);
93431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        invalidate();
93531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
93631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9370280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
9380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            boolean insertAtFirst, int intersectX, int intersectY) {
9390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
9400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
94131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final int[] cellXY = new int[2];
9430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
9440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
9450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
9460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
9470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellXY[0], cellXY[1]);
94831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
94931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9500280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
95100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
95200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
9530280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        CellLayout cellLayout;
954a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originX = x - xOffset;
955a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originY = y - yOffset;
956c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
9574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            cellLayout = findMatchingPageForDragOver(dragView, originX, originY, xOffset, yOffset);
958a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (cellLayout == null) {
959a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                // cancel the drag if we're not over a mini-screen at time of drop
960a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                // TODO: maybe add a nice fade here?
961a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                return;
962a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
9630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
9640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
9650280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
9664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cellLayout, mTempOriginXY);
9670280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
9680280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
9690280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        } else {
9700280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout = getCurrentDropLayout();
971a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
972c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
97331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
974a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            onDropExternal(originX, originY, dragInfo, cellLayout);
97531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
97631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Move internally
97731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragInfo != null) {
97831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final View cell = mDragInfo.cell;
979a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
9806a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka                mTargetCell = findNearestVacantArea(originX, originY,
981aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout,
982aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        mTargetCell);
983c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
984c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                int screen = indexOfChild(cellLayout);
985c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                if (screen != mDragInfo.screen) {
986c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                    final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
987c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                    originalCellLayout.removeView(cell);
988c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                    addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
989c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                            mDragInfo.spanX, mDragInfo.spanY);
990c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                }
991aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                cellLayout.onDropChild(cell);
99231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
993aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // update the item's position after drop
99484f296c106cb1c7b6d3ae6c6d5508a17f1324e29Romain Guy                final ItemInfo info = (ItemInfo) cell.getTag();
9950280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
9960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
997aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                lp.cellX = mTargetCell[0];
998aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                lp.cellY = mTargetCell[1];
99960587efe1a60ed698db9e2cafcd48f2c3fc8aa40Michael Jurka                cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
1000845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka                        mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
1001aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
100231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                LauncherModel.moveItemInDatabase(mLauncher, info,
1003c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                        LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1004aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        lp.cellX, lp.cellY);
100531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
100631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
100731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
100831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1009aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
1010aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
1011de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        getCurrentDropLayout().onDragEnter(dragView);
10121262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        showOutlines();
101331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
101431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1015440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
10166569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            DragView dragView, Object dragInfo) {
10176569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1018c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
10190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // If we're shrunken, don't let anyone drag on folders/etc  that are on the mini-screens
10200280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return null;
10210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1022440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
1023440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
1024440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
1025440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
10266569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
1027440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
1028440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1029440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
1030440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
1031440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
1032440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
1033440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
1034440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
1035440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
1036440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
1037440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
1038440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
10390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointX += mScrollX - currentLayout.getLeft();
10400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointY += mScrollY - currentLayout.getTop();
1041440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1042440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
1043440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
1044440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
1045440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
1046440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
1047440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
1048440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
1049440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
1050440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
1051440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
1052440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
1053440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
1054440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
10556569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
10564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
10574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
10584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
10594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
10604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
10614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
10624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy) {
10634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       mapPointFromSelfToChild(v, xy, null);
10644516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
10654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
10664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
10674516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
10684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
10694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
10704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
10714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * if cachedInverseMatrix is not null, this method will just use that matrix instead of
10724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * computing it itself; we use this to avoid redudant matrix inversions in
10734516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * findMatchingPageForDragOver
10744516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
10754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
10764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
10774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       if (cachedInverseMatrix == null) {
10784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           v.getMatrix().invert(mTempInverseMatrix);
10794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           cachedInverseMatrix = mTempInverseMatrix;
10804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       }
10814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] = xy[0] + mScrollX - v.getLeft();
10824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] = xy[1] + mScrollY - v.getTop();
10834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       cachedInverseMatrix.mapPoints(xy);
10844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
10854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
10864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
10874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
10884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from this CellLayout's coordinate space to
10894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * the parent View's coordinate space. The argument xy is modified with the return result.
10904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
10914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
10924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromChildToSelf(View v, float[] xy) {
10934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       v.getMatrix().mapPoints(xy);
10944516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] -= (mScrollX - v.getLeft());
10954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] -= (mScrollY - v.getTop());
10964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
10974516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
10984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    static private float squaredDistance(float[] point1, float[] point2) {
10994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceX = point1[0] - point2[0];
11004516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceY = point2[1] - point2[1];
11014516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return distanceX * distanceX + distanceY * distanceY;
11020280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
11030280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
11044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
11054516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
11064516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Returns true if the passed CellLayout cl overlaps with dragView
11074516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
11084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
11094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    boolean overlaps(CellLayout cl, DragView dragView,
11104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
11114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the coordinates of the item being dragged to the CellLayout's coordinates
11124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemTopLeft = mTempDragCoordinates;
11134516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[0] = dragViewX + dragView.getScaledDragRegionXOffset();
11144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[1] = dragViewY + dragView.getScaledDragRegionYOffset();
11154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
11164516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getScaledDragRegionWidth();
11174516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getScaledDragRegionHeight();
11184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11194516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the dragged item's top left coordinates
11204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // to the CellLayout's local coordinates
11214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
11224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
11234516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
11244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
11264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the dragged item's bottom right coordinates
11274516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // to the CellLayout's local coordinates
11284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
11294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
11304516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
11314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
11334516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float overlap = (overlapRegionRight - overlapRegionLeft) *
11344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                         (overlapRegionBottom - overlapRegionTop);
11354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (overlap > 0) {
11364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    return true;
11374516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                }
11384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka             }
11394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        }
11404516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return false;
11414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    }
1142a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
11434516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
11444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
11454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * This method returns the CellLayout that is currently being dragged to. In order to drag
11464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
11474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
11484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
11494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Return null if no CellLayout is currently being dragged over
11504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
11514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
11524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private CellLayout findMatchingPageForDragOver(
11534516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            DragView dragView, int originX, int originY, int offsetX, int offsetY) {
11544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which ones overlap
11554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // with the item being dragged and then choose the one that's closest to the touch point
1156a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
1157a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
11580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float smallestDistSoFar = Float.MAX_VALUE;
11594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
1160a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
1161a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
1162a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
11634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            final float[] touchXy = mTempTouchCoordinates;
11644516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[0] = originX + offsetX;
11654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[1] = originY + offsetY;
1166a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
11674516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the touch coordinates to the CellLayout's local coordinates
11684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // If the touch point is within the bounds of the cell layout, we can return immediately
11690280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cl.getMatrix().invert(mTempInverseMatrix);
11704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
11714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
11734516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
11744516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                return cl;
11754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
11764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
11784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Get the center of the cell layout in screen coordinates
11794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
11804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[0] = cl.getWidth()/2;
11814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[1] = cl.getHeight()/2;
11824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                mapPointFromChildToSelf(cl, cellLayoutCenter);
11834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[0] = originX + offsetX;
11854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[1] = originY + offsetY;
11864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Calculate the distance between the center of the CellLayout
11884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // and the touch point
11894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float dist = squaredDistance(touchXy, cellLayoutCenter);
11904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (dist < smallestDistSoFar) {
11920280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    smallestDistSoFar = dist;
1193a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
1194a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
11954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
1196a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
11970280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
11980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (bestMatchingScreen != mDragTargetLayout) {
1199a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (mDragTargetLayout != null) {
12000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                mDragTargetLayout.onDragExit();
1201a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
1202a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            mDragTargetLayout = bestMatchingScreen;
12031262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            // TODO: Should we be calling mDragTargetLayout.onDragEnter() here?
1204a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1205a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
1206a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
1207a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1208440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1209440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
12100280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        CellLayout currentLayout;
12110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int originX = x - xOffset;
12120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int originY = y - yOffset;
1213c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
12144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            currentLayout = findMatchingPageForDragOver(
12154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    dragView, originX, originY, xOffset, yOffset);
12160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
12170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            if (currentLayout == null) {
12180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                return;
12190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
12200280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
12210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            currentLayout.setHover(true);
12220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
12230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
12240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
12254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(currentLayout, mTempOriginXY);
12260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
12270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
12280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        } else {
12290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            currentLayout = getCurrentDropLayout();
12300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1231440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1232976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        final ItemInfo item = (ItemInfo)dragInfo;
12336569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
12346569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (dragInfo instanceof LauncherAppWidgetInfo) {
12356569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
12366569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
12376569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            if (widgetInfo.spanX == -1) {
12386569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                // Calculate the grid spans needed to fit this widget
12398f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy                int[] spans = currentLayout.rectToCell(widgetInfo.minWidth, widgetInfo.minHeight, null);
12406569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                item.spanX = spans[0];
12416569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                item.spanY = spans[1];
12426569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            }
12436569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
1244a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
12454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        if (source instanceof AllAppsPagedView) {
1246a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // This is a hack to fix the point used to determine which cell an icon from the all
1247a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // apps screen is over
1248a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (item != null && item.spanX == 1 && currentLayout != null) {
1249a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                int dragRegionLeft = (dragView.getWidth() - currentLayout.getCellWidth()) / 2;
1250a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1251a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                originX += dragRegionLeft - dragView.getDragRegionLeft();
1252a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                if (dragView.getDragRegionWidth() != currentLayout.getCellWidth()) {
1253a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    dragView.setDragRegion(dragView.getDragRegionLeft(), dragView.getDragRegionTop(),
1254a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                            currentLayout.getCellWidth(), dragView.getDragRegionHeight());
1255a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
1256a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
1257a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
12581262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
12591262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        // When touch is inside the scroll area, skip dragOver actions for the current screen
12601262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mInScrollArea) {
12611262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            if (currentLayout != mDragTargetLayout) {
12621262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                if (mDragTargetLayout != null) {
12631262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                    mDragTargetLayout.onDragExit();
12641262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                }
1265de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                currentLayout.onDragEnter(dragView);
12661262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                mDragTargetLayout = currentLayout;
12676569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            }
12686569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
12691262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            // only visualize the drop locations for moving icons within the home screen on tablet
12701262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            // on phone, we also visualize icons dragged in from All Apps
12711262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            if ((!LauncherApplication.isScreenXLarge() || source == this)
12721262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                    && mDragTargetLayout != null) {
12731262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                final View child = (mDragInfo == null) ? null : mDragInfo.cell;
12741262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
12751262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
12761262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                mDragTargetLayout.visualizeDropLocation(
12771262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                        child, localOriginX, localOriginY, item.spanX, item.spanY);
12781262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            }
1279976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
128031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
128131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1282aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
1283aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
12846569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
12850280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mDragTargetLayout.onDragExit();
12866569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            mDragTargetLayout = null;
12876569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
12881262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mIsPageMoving) {
12891262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
12901262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
129131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
129231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1293aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1294aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
129531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
129631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1297aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
12982b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
12992b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
13002b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
13012b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
13022b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
13032b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
13042b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
13052b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
13062b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
13072b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
13080280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
13092b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            onDropExternal(0, 0, dragInfo, cl, false);
13102b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
13112b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
13120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mLauncher.showOutOfSpaceMessage();
13132b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
13142b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
13152b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
13160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    // Drag from somewhere else
1317aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1318aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
13190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int screen = indexOfChild(cellLayout);
13200280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (dragInfo instanceof PendingAddItemInfo) {
13210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
13220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // When dragging and dropping from customization tray, we deal with creating
13230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // widgets/shortcuts/folders in a slightly different way
13240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            int[] touchXY = new int[2];
13250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[0] = x;
13260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[1] = y;
13270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            switch (info.itemType) {
13280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
13290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addAppWidgetFromDrop(info.componentName, screen, touchXY);
13300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
13310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
13320280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
13330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
13340280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
13350280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
13360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
13370280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                default:
13380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    throw new IllegalStateException("Unknown item type: " + info.itemType);
13390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
13400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
13410280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return;
13420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
13430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
13440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        // This is for other drag/drop cases, like dragging from All Apps
134531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
134631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1347af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
134831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
134931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
135031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
135131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1352e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
135331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1354aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
135531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1356aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1357aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
135831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
135931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
136031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
13610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    cellLayout, ((UserFolderInfo) info));
1362af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
136331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
13640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            throw new IllegalStateException("Unknown item type: " + info.itemType);
136531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
136631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13676569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
13686569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
13690280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
13706569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
13717ded67cd64153cd41bb133a6aab11b3254b4a5d9Michael Jurka            mTargetCell = findNearestVacantArea(x, y, 1, 1, null, cellLayout, mTargetCell);
1372aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1373aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1374aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
13756569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
137631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1377af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
13780280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1379aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1380af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
138131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1382aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
138370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
138470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
138570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
138670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
138770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
13880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
138970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
139070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
139131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
139270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
13930280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * Return the current CellInfo describing our current drag; this method exists
13940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * so that Launcher can sync this object with the correct info when the activity is created/
13950280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * destroyed
13960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     *
13970280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     */
13980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public CellLayout.CellInfo getDragInfo() {
13990280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return mDragInfo;
14000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
14010280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
14020280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    /**
140370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * {@inheritDoc}
140470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
140570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    public boolean acceptDrop(DragSource source, int x, int y,
140600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
14070280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        CellLayout layout;
1408c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
14094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            layout = findMatchingPageForDragOver(
14104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    dragView, x - xOffset, y - yOffset, xOffset, yOffset);
14110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            if (layout == null) {
14120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                // cancel the drag if we're not over a mini-screen at time of drop
14130280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                return false;
14140280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
14150280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        } else {
14160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            layout = getCurrentDropLayout();
14170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1418c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final CellLayout.CellInfo dragCellInfo = mDragInfo;
1419c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1420c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
14214c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1422c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
14234c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
14240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (layout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
14250e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return true;
14260e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        } else {
14270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mLauncher.showOutOfSpaceMessage();
14280e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return false;
14290e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        }
143070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1431aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
143270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
143370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
143470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
14356a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka    private int[] findNearestVacantArea(int pixelX, int pixelY,
143670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
14376569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
14385f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
14395f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelY = pixelY - (layout.getTop() - mScrollY);
14406569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
144170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
14420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return layout.findNearestVacantArea(
1443fc9f07d42511231a26fa182c32e2efaa0f41d478Michael Jurka                localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
144470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1445aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
14468f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
14478f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
14488f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
14498f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
14500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
14518f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
14528f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
145331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
145431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
145531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
145631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
145700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
145800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
145931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
146031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
146131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1462aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
146331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
146431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
146531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
146600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
146700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
146800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1469aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
147031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
147131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
147231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragInfo != null) {
147331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
147431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.onDropAborted(mDragInfo.cell);
147531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
147631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
147731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
147831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
147931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
148031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14810280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
14820280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return true;
14830280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
14840280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
14850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
14860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
14870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
14880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
14890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
14900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
14910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
149231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
1493c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
14940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
149531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
149631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
149731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
149931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
1500c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
15010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
150231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
150331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1504138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
15051262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
15061262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onEnterScrollArea(int direction) {
15071262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        mInScrollArea = true;
15081262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        final int screen = getCurrentPage() + ((direction == DragController.SCROLL_LEFT) ? -1 : 1);
15091262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (0 <= screen && screen < getChildCount()) {
15101262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            ((CellLayout) getChildAt(screen)).setHover(true);
15111262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
15121262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
15131262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (mDragTargetLayout != null) {
15141262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            mDragTargetLayout.onDragExit();
15151262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            mDragTargetLayout = null;
15161262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
15171262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
15181262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
15191262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
15201262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onExitScrollArea() {
15211262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        mInScrollArea = false;
15221262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        final int childCount = getChildCount();
15231262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        for (int i = 0; i < childCount; i++) {
15241262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            ((CellLayout) getChildAt(i)).setHover(false);
15251262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
15261262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
15271262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
152831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1529dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
153031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
153131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
153231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
153331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
153431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
153531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
153631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
153731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
1538aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
153931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
154031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
154131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
154231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
154331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
154431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
154531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
154631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
154731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
154831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
154931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
155031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
155131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
155231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
155331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
155431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
155531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
155631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
155731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
155831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
155931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
156031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
156131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
156231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
156364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
1564dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
15655c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
1566629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
1567574d20ec84551370987dde530c27ec493bdef564Romain Guy
156864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
156964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
157064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
157164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
157264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
157364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
1574dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
157531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1576629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1577629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
1578629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
1579629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
1580629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
1581629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
1582aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1583629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
1584629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1585629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
1586629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
1587aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
15880589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
15890589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
1590629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
1591629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
1592aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
159364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
159464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
159564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
159664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
159764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
159864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
159964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1600629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1601629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
1602629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
16030589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
16040589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
1605629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
1606629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
1607aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1608629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
16090589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
1610629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
1611629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
1612aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
161364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
161464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
161564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
161664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
161773013bf94f49ffbacba2b8300f6a2dd4eeebbd13Brad Fitzpatrick                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
161864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
161964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
162064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
1621629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
1622629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1623aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1624629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
1625629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
1626629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
1627aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
1628aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
1629629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1630629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
1631629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
1632629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
1633629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
1634629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
1635629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1636f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
163764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
163864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
163964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1640aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
164164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
164264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1643629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1644629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
1645629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
1646629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
1647629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
1648e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
164964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
165064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
165164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1652aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
165364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
165464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1655629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1656574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
1657574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1658aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1659629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
1660629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1661629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
1662629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
1663629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
1664629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
1665629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
1666574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1667aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1668629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
1669629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
1670629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
16715c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
167231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
1673629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
167431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
167531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1676f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
167764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
1678dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
1679dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
1680f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1681f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
1682f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
1683f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
1684f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
16850589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
16860589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
1687f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
1688f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
1689f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
1690f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
1691f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
1692f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
169364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
169464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
1695aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
169664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
169764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
169864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
169964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
170064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
170164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
170264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
170364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
1704f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
1705f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
1706f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
1707f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
1708f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
1709f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
171014f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
1711c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1712c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
1713c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        } else if (animate) {
1714c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            snapToPage(mDefaultPage);
1715c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
17160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
1717c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
17180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
171931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
172031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17218a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
17228a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
17238a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
17240142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
17250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
17268a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
17278a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
17280142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
17290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
17300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
173131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
17330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
173431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
17350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
173631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
1737