Workspace.java revision a997ac26664befbd0d5b172e36ef9e8b2c63b435
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
19a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport java.util.ArrayList;
20a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport java.util.HashSet;
21495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell
220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.Animator;
23ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroyimport android.animation.Animator.AnimatorListener;
2418014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurkaimport android.animation.AnimatorListenerAdapter;
25b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.AnimatorSet;
260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.ObjectAnimator;
270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.PropertyValuesHolder;
288f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.app.WallpaperManager;
29629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetManager;
30629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
31a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.content.ClipData;
32a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.content.ClipDescription;
33495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.ComponentName;
3431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent;
36495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.pm.PackageManager;
375c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.content.pm.ProviderInfo;
387247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.content.res.Resources;
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.TypedArray;
404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Bitmap;
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
42a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.graphics.Matrix;
43a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.graphics.Paint;
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
45a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.graphics.RectF;
464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Region.Op;
47f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.graphics.drawable.Drawable;
485c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.net.Uri;
49956091ba7863bd72086275e61084864994dd6fa7Joe Onoratoimport android.os.IBinder;
50495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcelable;
5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
52291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandlerimport android.util.Log;
53a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.DragEvent;
5431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
5531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
56f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
57a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.widget.Toast;
5831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport com.android.launcher.R;
60edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
64aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
67dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
68e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
693a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
71dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
72dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
73dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
74a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
75f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    // Y rotation to apply to the workspace screens
76f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final float WORKSPACE_ROTATION = 12.5f;
77a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
78a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // These are extra scale factors to apply to the mini home screens
79a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // so as to achieve the desired transform
801b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private static final float EXTRA_SCALE_FACTOR_0 = 0.972f;
81a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
821b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private static final float EXTRA_SCALE_FACTOR_2 = 1.10f;
83a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
84f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DELAY = 300;
85f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DURATION = 300;
86f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_IN_DURATION = 100;
87f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
883e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // These animators are used to fade the background
89472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeInAnimation;
90472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeOutAnimation;
91f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private float mBackgroundAlpha = 0;
92f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
938f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
94aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    private boolean mPageMoving = false;
9821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
103aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
10470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
10570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
10670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
10770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1096569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
1106569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
1116569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
1126569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
1136569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
1150589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
11600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
117aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // These are temporary variables to prevent having to allocate a new object just to
1194516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
12170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
1220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private float[] mTempOriginXY = new float[2];
123a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
1244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempTouchCoordinates = new float[2];
1254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempCellLayoutCenterCoordinates = new float[2];
126a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
1270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private Matrix mTempInverseMatrix = new Matrix();
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
129d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
130d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1328a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1338a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
134aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1351262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    // State variable that indicates whether the pages are small (ie when you're
136dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
137c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsSmall = false;
138c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsInUnshrinkAnimation = false;
139b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
1403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private enum ShrinkPosition {
1413e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM_HIDDEN, SHRINK_TO_BOTTOM_VISIBLE };
1423e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ShrinkPosition mShrunkenState;
143883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    private boolean mWaitingToShrink = false;
144883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    private ShrinkPosition mWaitingToShrinkPosition;
145dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
1461262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    private boolean mInScrollArea = false;
1471b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private boolean mInDragMode = false;
1481262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1498e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
1504be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap mDragOutline = null;
1518e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final Rect mTempRect = new Rect();
1528e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final int[] mTempXY = new int[2];
1534be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
154a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    // Paint used to draw external drop outline
155a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    private final Paint mExternalDragOutlinePaint = new Paint();
156a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
16631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
17331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
17431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1775f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
1785f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
1795f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFadeInAdjacentScreens = false;
1805f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1828f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
183aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
184aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
185aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
186d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
187d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
1880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
191d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
1920d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
1930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
19631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
19831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
2000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
2010589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
2020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
2030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
2040589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
2050589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
206a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        mExternalDragOutlinePaint.setAntiAlias(true);
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
208472b281d5cb4f5660df981a6c912266b9f5703feChet Haase        mUnshrinkAnimationListener = new AnimatorListenerAdapter() {
209c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            public void onAnimationStart(Animator animation) {
210c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = true;
211c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            }
212b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationEnd(Animator animation) {
213c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = false;
214dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
215dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
2160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
21831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
220f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected int getScrollMode() {
221f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        if (LauncherApplication.isScreenXLarge()) {
222f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.QUINTIC_MODE;
223f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        } else {
224f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.OVERSHOOT_MODE;
225f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
226f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
227f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
228f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
23321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
24431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
26021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
26131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
26921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
27131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
2800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
281aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
282aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
283aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
284aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
291dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
292dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
294dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
2950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
2960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
2980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
299aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
300aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
301aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
302aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
3110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
3170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
3210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
3220142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
32631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
32731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
33131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
340aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
341aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
342aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
343aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
35031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
358291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
359291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
360291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
36131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
36931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
37031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
37131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
37231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
373aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3746569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
375845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
376f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        boolean markCellsAsOccupied = !(child instanceof Folder);
377f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
378aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
379aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
3806569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
381aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
382aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
383aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
3850d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
38800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
389aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
39000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
39231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
393dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
394dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
395c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
3962b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
39796226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
39821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        } else if (!mPageMoving) {
39921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            if (v == getChildAt(mCurrentPage - 1)) {
40021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage - 1);
40121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
40221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            } else if (v == getChildAt(mCurrentPage + 1)) {
40321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage + 1);
40421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
40521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            }
406dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
407dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
4080e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
4090e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
4105f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4115f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
412c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4135f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4145f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4155f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4165f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
4175f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4185f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4195f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4205f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
421c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4225f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4235f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4245f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4255f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.onInterceptTouchEvent(ev);
4265f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4275f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4281adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    @Override
4291adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    protected void determineScrollingStart(MotionEvent ev) {
4301adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) super.determineScrollingStart(ev);
4311adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    }
4321adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka
4331262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageBeginMoving() {
4340142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
4350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
43616fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage, mNextPage);
4370142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
4390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
44016fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
44131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
442f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        showOutlines();
44321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = true;
44431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
44531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4461262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageEndMoving() {
44716fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        clearChildrenCache();
4481262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        // Hide the outlines, as long as we're not dragging
4491262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mDragController.dragging()) {
4501262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
4511262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
45221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = false;
4530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
4540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
4560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
4570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
4580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
4600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
4610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
4620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
4690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
4700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
4710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4728f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
473798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
474798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
475798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
476798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
47786f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
47886f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
47986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
48086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
48186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
48286f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
48386f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
48486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
48586f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
486956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
4878f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
488aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
489f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void showOutlines() {
4903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
4913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
4923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
493472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
494472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
4953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeInAnimation.start();
4963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
497f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
498f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
499f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void hideOutlines() {
5003e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
5013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
5023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
503472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
504472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
5053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
5063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.start();
5073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
508f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
509f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
510f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void setBackgroundAlpha(float alpha) {
511f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        mBackgroundAlpha = alpha;
512f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
513f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
514f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            cl.setBackgroundAlpha(alpha);
515f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
516f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
517f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
518f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public float getBackgroundAlpha() {
519f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        return mBackgroundAlpha;
520f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
521f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
522f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
523f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected void screenScrolled(int screenCenter) {
52421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        final int halfScreenSize = getMeasuredWidth() / 2;
52521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
5261b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
5271b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            if (cl != null) {
5281b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                int totalDistance = cl.getMeasuredWidth() + mPageSpacing;
52921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int delta = screenCenter - (getChildOffset(i) -
53021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                        getRelativeChildOffset(i) + halfScreenSize);
531f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
53221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float scrollProgress = delta/(totalDistance*1.0f);
53321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.min(scrollProgress, 1.0f);
53421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.max(scrollProgress, -1.0f);
535f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
5361b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                float mult =  mInDragMode ? 1.0f : Math.abs(scrollProgress);
5371b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                cl.setBackgroundAlphaMultiplier(mult);
5381b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
53921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float rotation = WORKSPACE_ROTATION * scrollProgress;
5401b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                cl.setRotationY(rotation);
541f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            }
542f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
543f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
544f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
54500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
54600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
547956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
54800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
54900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
55000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
55131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
55228750fba6a2d141eb9a1e566718c17236030b815Michael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
5530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
554aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
55579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
55679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
557883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (mWaitingToShrink) {
558883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            shrink(mWaitingToShrinkPosition, false);
559883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrink = false;
56079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
56179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
562aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
563aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
564aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
5650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
566aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
56731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
56831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
56931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
571c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
5720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
5730142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
5740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
5750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
5760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
5770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
5790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
5800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
5810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
58231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
58331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
58431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
58531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
58631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
587678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
58831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
58931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
59031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
59131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
5920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
59331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
59431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
59531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
59631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
59731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
599c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
600678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
60131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
6020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
60331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
6040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
6050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
60631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
60731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
60831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
60931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
61031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
6117bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
6127bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
61354dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
61454dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
6156b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
6167bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
6177bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
6187bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
6197bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
6207bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
6217bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
6220142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
6230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
6240142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
6250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
6260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
6273a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
628aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
629dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
630fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6310142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
6320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
633fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6340142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
63531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
63631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
63731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
63831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
63931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
64031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
64131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
642dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
643dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
64431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
64531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
64631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
64731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
64831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
64931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
65031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
6512bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
6522bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
6532bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
6542bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
6552bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
6563e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            setCurrentPage(mCurrentPage);
6577c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
65831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
65931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
66131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
662aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
66301f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
66401f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
66501f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
66601f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
6676b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
6680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
66901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
67001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
67101f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
6720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
673213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
674213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
675213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
67679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
67779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
67879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
67979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
680883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, animated);
681213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
682213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
683a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float getYScaleForScreen(int screen) {
684a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int x = Math.abs(screen - 2);
685a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
686a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // TODO: This should be generalized for use with arbitrary rotation angles.
687a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        switch(x) {
688a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 0: return EXTRA_SCALE_FACTOR_0;
689a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 1: return EXTRA_SCALE_FACTOR_1;
690a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 2: return EXTRA_SCALE_FACTOR_2;
691a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
692a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        return 1.0f;
693a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
694a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
695dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
6960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
697883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (mFirstLayout) {
698883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
699883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
700883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
701883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // to get our width so we can layout the mini-screen views correctly
702883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrink = true;
703883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrinkPosition = shrinkPosition;
704883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            return;
705883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        }
706dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
7073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        mShrunkenState = shrinkPosition;
7083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        // Stop any scrolling, move to the current page right away
710a997ac26664befbd0d5b172e36ef9e8b2c63b435Michael Jurka        setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage);
7113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
7123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7135f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // we intercept and reject all touch events when we're small, so be sure to reset the state
7145f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mTouchState = TOUCH_STATE_REST;
7155f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mActivePointerId = INVALID_POINTER;
7165f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
7171b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
7181b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        currentPage.setBackgroundAlphaMultiplier(1.0f);
7191b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
7207247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
721dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
722213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
7230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7240142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
7250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
7260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
7270142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7280142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
7290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
730a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
731dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
732dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
733a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
734213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
735df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        boolean isPortrait = getMeasuredHeight() > getMeasuredWidth();
736df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        float newY = (isPortrait ?
737ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginPortrait) :
738ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginLandscape));
7393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float finalAlpha = 1.0f;
7403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float extraShrinkFactor = 1.0f;
7413e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
7423e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             newY = screenHeight - newY - scaledPageHeight;
7433e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
7443e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7453e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // We shrink and disappear to nothing in the case of all apps
7463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // (which is when we shrink to the bottom)
7470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
7483e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            finalAlpha = 0.0f;
7493e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            extraShrinkFactor = 0.1f;
7500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
751b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            newY = screenHeight / 2 - scaledPageHeight / 2;
752b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            finalAlpha = 1.0f;
753b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_TOP) {
754ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung            newY = (isPortrait ?
755ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginPortrait) :
756ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginLandscape));
757213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
758dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
759dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
760dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
761dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
762dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
7630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
764a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
765a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // We are going to scale about the center of the view, so we need to adjust the positions
766a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // of the views accordingly
767a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newX -= (pageWidth - scaledPageWidth) / 2.0f;
768a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newY -= (pageHeight - scaledPageHeight) / 2.0f;
769dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
770dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
771a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
772f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            float rotation = (-i + 2) * WORKSPACE_ROTATION;
773a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
774a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleY = getYScaleForScreen(i);
775a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
77679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
7777247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
778472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(cl,
779472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("x", newX),
780472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("y", newY),
781472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleX",
7823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleX * extraShrinkFactor),
783472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleY",
7843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor),
785472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha),
786472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("alpha", finalAlpha),
787472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("rotationY", rotation));
788472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.setDuration(duration);
789472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.start();
79079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
79179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
79279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
793883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setScaleX(SHRINK_FACTOR * rotationScaleX * extraShrinkFactor);
794883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setScaleY(SHRINK_FACTOR * rotationScaleY * extraShrinkFactor);
795883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setBackgroundAlpha(finalAlpha);
7963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                cl.setAlpha(finalAlpha);
797a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                cl.setRotationY(rotation);
79879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
799dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
800a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            newX += scaledPageWidth + extraScaledSpacing;
801dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
802dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
803dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
804dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
8053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
8073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
8083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkPosition state, int spanX, int spanY) {
8123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, true, spanX, spanY);
8133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsHelper(
8163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ShrinkPosition state, boolean isDragHappening, int spanX, int spanY) {
8173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        final int screenCount = getChildCount();
8183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        for (int i = 0; i < screenCount; i++) {
8193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
8203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            switch (state) {
8223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_TOP:
8233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        boolean showDropHighlight = i == mCurrentPage;
8253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        cl.setAcceptsDrops(showDropHighlight);
8263e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        break;
8273e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8283e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // otherwise, fall through below and mark non-full screens as accepting drops
8293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_HIDDEN:
8303e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_VISIBLE:
8313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8323e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // even if a drag isn't happening, we don't want to show a screen as
8333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // accepting drops if it doesn't have at least one free cell
8343e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanX = 1;
8353e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanY = 1;
8363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // the page accepts drops if we can find at least one empty spot
8383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
8393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    break;
8403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                default:
8413e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                     throw new RuntimeException(
8423e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkPosition");
8433e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
8443e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8453e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8473e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    /*
8483e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8493e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
8503e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
8513e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8523e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * These methods mark the appropriate pages as accepting drops (which alters their visual
8533e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * appearance) and, if the pages are hidden, makes them visible.
8543e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8553e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     */
8563e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemSpans(int spanX, int spanY) {
8573e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsDuringDrag(mShrunkenState, spanX, spanY);
8583e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
8593e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE, true);
8603e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8613e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8623e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8633e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemMinSize(int minWidth, int minHeight) {
8643e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        int[] spanXY = CellLayout.rectToCell(getResources(), minWidth, minHeight, null);
8653e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        onDragStartedWithItemSpans(spanXY[0], spanXY[1]);
8663e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8673e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8683e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
8693e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // never dragged over
8703e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStopped() {
8713e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
8723e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8733e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
874dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
8752b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
8760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
8774cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
8784cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
8794cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
8800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
8814cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
8824cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
8830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
8844cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
8854cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
88621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    @Override
88721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    protected boolean handlePagingClicks() {
88821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        return true;
88921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    }
89021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
8910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
892b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
8935f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
8945f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int delta = newX - mScrollX;
8954cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
896b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
897b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
898b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
899b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
900b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
9010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
902c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            unshrink();
903b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
904dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
905dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
9064cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
9074cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
9084cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
9094cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
9104cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
911b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
912c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mIsSmall = false;
913b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            AnimatorSet s = new AnimatorSet();
914b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
9154cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
9164cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
917b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
9187247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
9195f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
920f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                float rotation = 0.0f;
921f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
922f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (i < mCurrentPage) {
923f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = WORKSPACE_ROTATION;
924f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                } else if (i > mCurrentPage) {
925f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = -WORKSPACE_ROTATION;
926f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                }
927f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
9284cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
929472b281d5cb4f5660df981a6c912266b9f5703feChet Haase
9304cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    s.playTogether(
931472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationX", 0.0f).setDuration(duration),
932472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationY", 0.0f).setDuration(duration),
933472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleX", 1.0f).setDuration(duration),
934472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleY", 1.0f).setDuration(duration),
935472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "backgroundAlpha", 0.0f).setDuration(duration),
936472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "alpha", finalAlphaValue).setDuration(duration),
937472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "rotationY", rotation).setDuration(duration));
9384cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
9394cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
9404cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
9414cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
9424cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
9435f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setBackgroundAlpha(0.0f);
944f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setAlpha(finalAlphaValue);
945f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setRotationY(rotation);
9464cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
947b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
948c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            if (animated) {
949c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // If we call this when we're not animated, onAnimationEnd is never called on
950c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // the listener; make sure we only use the listener when we're actually animating
951c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                s.addListener(mUnshrinkAnimationListener);
952c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                s.start();
953c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            }
954dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
955dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
956dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
9574be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
9584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Draw the View v into the given Canvas.
9594be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     *
9604be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param v the view to draw
9614be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param destCanvas the canvas to draw on
9624be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param padding the horizontal and vertical padding to use when drawing
9634be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
9644be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private void drawDragView(View v, Canvas destCanvas, int padding) {
9654be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Rect clipRect = mTempRect;
9664be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.getDrawingRect(clipRect);
9674be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9684be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // For a TextView, adjust the clip rect so that we don't include the text label
9694be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        if (v instanceof TextView) {
9704be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            final int iconHeight = ((TextView)v).getCompoundPaddingTop() - v.getPaddingTop();
9714be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            clipRect.bottom = clipRect.top + iconHeight;
9724be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        }
9734be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9744be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // Draw the View into the bitmap.
9754be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
9764be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // they set scrollX and scrollY to large values to achieve centered text
9774be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9784be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.save();
9794be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
9804be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.clipRect(clipRect, Op.REPLACE);
9814be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.draw(destCanvas);
9824be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.restore();
9834be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
9844be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9854be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
9864be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
9874be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
9884be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
9894be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {
9904be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
9914be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
9924be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
9934be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9944be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
9954be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
9964be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
9974be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9984be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
9994be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10004be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10014be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
1002a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * Creates a drag outline to represent a drop (that we don't have the actual information for
1003a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * yet).  May be changed in the future to alter the drop outline slightly depending on the
1004a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * clip description mime data.
1005a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     */
1006a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    private Bitmap createExternalDragOutline(Canvas canvas, int padding) {
1007a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        Resources r = getResources();
1008a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int outlineColor = r.getColor(R.color.drag_outline_color);
1009a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int iconWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
1010a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int iconHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height);
1011a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int rectRadius = r.getDimensionPixelSize(R.dimen.external_drop_icon_rect_radius);
1012a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int inset = (int) (Math.min(iconWidth, iconHeight) * 0.2f);
1013a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final Bitmap b = Bitmap.createBitmap(
1014a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                iconWidth + padding, iconHeight + padding, Bitmap.Config.ARGB_8888);
1015a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1016a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        canvas.setBitmap(b);
1017a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        canvas.drawRoundRect(new RectF(inset, inset, iconWidth - inset, iconHeight - inset),
1018a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                rectRadius, rectRadius, mExternalDragOutlinePaint);
1019a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
1020a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1021a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        return b;
1022a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
1023a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1024a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
10254be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to show when the given View is being dragged around.
10264be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
10274be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
10284be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
10294be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
10304be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
10314be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                mDragOutline.getWidth(), mDragOutline.getHeight(), Bitmap.Config.ARGB_8888);
10324be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10334be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
10344be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.drawBitmap(mDragOutline, 0, 0, null);
10354be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
10368e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
10374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10384be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
10394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
104131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
104231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
1043aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
104431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
10457984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
104631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
104731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
1048aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
104931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
10500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
1051aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
105208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        CellLayout current = getCurrentDropLayout();
105331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
105431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
10554be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10564be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.clearFocus();
10574be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.setPressed(false);
10584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10594be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Canvas canvas = new Canvas();
10604be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10618e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        // We need to add extra padding to the bitmap to make room for the glow effect
10628e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
10638e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy
10644be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The outline is used to visualize where the item will land if dropped
10658e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mDragOutline = createDragOutline(child, canvas, bitmapPadding);
10664be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10674be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The drag bitmap follows the touch point around on the screen
10688e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final Bitmap b = createDragBitmap(child, canvas, bitmapPadding);
10694be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10704be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpWidth = b.getWidth();
10714be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpHeight = b.getHeight();
10724be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.getLocationOnScreen(mTempXY);
10734be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
10744be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
10754be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
10764be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                child.getTag(), DragController.DRAG_ACTION_MOVE, null);
10774be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        b.recycle();
107831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
107931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10800280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
10810280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            boolean insertAtFirst, int intersectX, int intersectY) {
10820280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
10830280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
108431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10850280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final int[] cellXY = new int[2];
10860280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
10870280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
10880280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
10890280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
10900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellXY[0], cellXY[1]);
109131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
109231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1093ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    private void setPositionForDropAnimation(
1094ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            View dragView, int dragViewX, int dragViewY, View parent, View child) {
1095ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
1096ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1097ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // Based on the position of the drag view, find the top left of the original view
1098ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
1099ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
1100ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewX -= getResources().getInteger(R.integer.config_dragViewOffsetX);
1101ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewY -= getResources().getInteger(R.integer.config_dragViewOffsetY);
1102ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1103ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // Set its old pos (in the new parent's coordinates); the CellLayout will
1104ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // animate it from this position during the next layout pass
1105ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldX = viewX - (parent.getLeft() - mScrollX);
1106ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldY = viewY - (parent.getTop() - mScrollY);
1107ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    }
11080280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
110900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
111000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
1111ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1112ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originX = x - xOffset;
1113ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originY = y - yOffset;
1114ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1115d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout == null) {
1116ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // Cancel the drag if we're not over a screen at time of drop
1117ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            if (mDragInfo != null) {
1118ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                // Set its position so the parent can animate it back
1119ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                final View parent = getChildAt(mDragInfo.screen);
1120ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                setPositionForDropAnimation(dragView, originX, originY, parent, mDragInfo.cell);
1121ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            }
1122d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            return;
1123d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
1124ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1125c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
11260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
11270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
11280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
1129d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
11300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
11310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
1132a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1133c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
113431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
1135d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
1136ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
113731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Move internally
1138ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            final View cell = mDragInfo.cell;
1139ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            mTargetCell = findNearestVacantArea(originX, originY,
1140ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
1141ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    mTargetCell);
1142ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1143ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            int screen = indexOfChild(mDragTargetLayout);
1144ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            if (screen != mDragInfo.screen) {
1145ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
1146ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                originalCellLayout.removeView(cell);
1147ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
1148ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                        mDragInfo.spanX, mDragInfo.spanY);
114931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1150ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            mDragTargetLayout.onDropChild(cell);
1151ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1152ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // update the item's position after drop
1153ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            final ItemInfo info = (ItemInfo) cell.getTag();
1154ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
1155ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
1156ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            lp.cellX = mTargetCell[0];
1157ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            lp.cellY = mTargetCell[1];
1158ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
1159ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
1160ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1161ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            LauncherModel.moveItemInDatabase(mLauncher, info,
1162ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1163ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy                    lp.cellX, lp.cellY);
1164ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1165ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // Prepare it to be animated into its new position
1166ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // This must be called after the view has been re-parented
1167ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            setPositionForDropAnimation(dragView, originX, originY, mDragTargetLayout, cell);
116831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
116931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
117031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1171aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
1172aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
117308ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        mDragTargetLayout = null; // Reset the drag state
117408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
1175d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall) {
117608ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            mDragTargetLayout = getCurrentDropLayout();
1177a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            mDragTargetLayout.onDragEnter();
1178d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            showOutlines();
11791b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            mInDragMode = true;
11801b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            CellLayout cl = (CellLayout) getChildAt(mCurrentPage);
11811b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            cl.setBackgroundAlphaMultiplier(1.0f);
1182d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
118331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
118431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
118518014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka    public DropTarget getDropTargetDelegate(DragSource source, int x, int y,
118618014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
11876569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1188c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1189d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
11900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return null;
11910280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1192440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
1193440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
1194440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
1195440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
11966569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
1197440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
1198440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1199440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
1200440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
1201440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
1202440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
1203440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
1204440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
1205440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
1206440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
1207440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
1208440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
12090280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointX += mScrollX - currentLayout.getLeft();
12100280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointY += mScrollY - currentLayout.getTop();
1211440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1212440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
1213440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
1214440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
1215440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
1216440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
1217440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
1218440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
1219440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
1220440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
1221440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
1222440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
1223440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
1224440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
12256569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1226a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
1227a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * Global drag and drop handler
1228a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     */
1229a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    @Override
1230a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    public boolean onDragEvent(DragEvent event) {
1231a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final CellLayout layout = (CellLayout) getChildAt(mCurrentPage);
1232a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int[] pos = new int[2];
1233a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        layout.getLocationOnScreen(pos);
1234a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        // We need to offset the drag coordinates to layout coordinate space
1235a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int x = (int) event.getX() - pos[0];
1236a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int y = (int) event.getY() - pos[1];
1237a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1238a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        switch (event.getAction()) {
1239a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_STARTED:
1240a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Check if we have enough space on this screen to add a new shortcut
1241a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (!layout.findCellForSpan(pos, 1, 1)) {
1242a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
1243a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1244a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return false;
1245a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1246a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1247a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            ClipDescription desc = event.getClipDescription();
1248a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (desc.filterMimeTypes(ClipDescription.MIMETYPE_TEXT_INTENT) != null) {
1249a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                // Create the drag outline
1250a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                // We need to add extra padding to the bitmap to make room for the glow effect
1251a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                final Canvas canvas = new Canvas();
1252a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
1253a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                mDragOutline = createExternalDragOutline(canvas, bitmapPadding);
1254a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1255a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                // Show the current page outlines to indicate that we can accept this drop
1256a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                showOutlines();
1257a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                layout.setHover(true);
1258a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                layout.onDragEnter();
1259a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
1260a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1261a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return true;
1262a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1263a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            break;
1264a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_LOCATION:
1265a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Visualize the drop location
1266a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
1267a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1268a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DROP:
1269a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Check if we have enough space on this screen to add a new shortcut
1270a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (!layout.findCellForSpan(pos, 1, 1)) {
1271a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
1272a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1273a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return false;
1274a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1275a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1276a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Try and add any shortcuts
1277a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            int newDropCount = 0;
1278a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final LauncherModel model = mLauncher.getModel();
1279a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final ClipData data = event.getClipData();
1280a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final int itemCount = data.getItemCount();
1281a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            for (int i = 0; i < itemCount; ++i) {
1282a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                final Intent intent = data.getItem(i).getIntent();
128355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                if (intent != null) {
128455cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    Object info = null;
128555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    if (model.validateShortcutIntent(intent)) {
128655cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
128755cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    } else if (model.validateWidgetIntent(intent)) {
128855cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        final ComponentName component = ComponentName.unflattenFromString(
128955cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                            intent.getStringExtra(InstallWidgetReceiver.EXTRA_APPWIDGET_COMPONENT));
129055cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        final AppWidgetProviderInfo appInfo =
129155cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                            model.findAppWidgetProviderInfoWithComponent(mContext, component);
129255cef262f97749300c2f6e764da0b00cbcb78879Winson Chung
129355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        PendingAddWidgetInfo createInfo = new PendingAddWidgetInfo();
129455cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
129555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.componentName = appInfo.provider;
129655cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.minWidth = appInfo.minWidth;
129755cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.minHeight = appInfo.minHeight;
129855cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.configurationData = intent.getParcelableExtra(
129955cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                                InstallWidgetReceiver.EXTRA_APPWIDGET_CONFIGURATION_DATA);
130055cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        info = createInfo;
130155cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    }
130255cef262f97749300c2f6e764da0b00cbcb78879Winson Chung
130355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    if (info != null) {
130455cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        onDropExternal(x, y, info, layout);
130555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        newDropCount++;
130655cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    }
1307a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                }
1308a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1309a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1310a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Show error message if we couldn't accept any of the items
1311a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (newDropCount <= 0) {
1312a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                Toast.makeText(mContext, "Only Shortcut Intents accepted.",
1313a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1314a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1315a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1316a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1317a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_ENDED:
1318a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Hide the page outlines after the drop
1319a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.setHover(false);
1320a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.onDragExit();
1321a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            hideOutlines();
1322a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1323a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        }
1324a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        return super.onDragEvent(event);
1325a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
1326a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
13274516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
13284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
13294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
13304516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
13314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
13324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
13334516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy) {
13344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       mapPointFromSelfToChild(v, xy, null);
13354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
13364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13374516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
13384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
13394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
13404516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
13414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
13424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * if cachedInverseMatrix is not null, this method will just use that matrix instead of
1343d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka    * computing it itself; we use this to avoid redundant matrix inversions in
13444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * findMatchingPageForDragOver
13454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
13464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
13474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
13484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       if (cachedInverseMatrix == null) {
13494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           v.getMatrix().invert(mTempInverseMatrix);
13504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           cachedInverseMatrix = mTempInverseMatrix;
13514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       }
13524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] = xy[0] + mScrollX - v.getLeft();
13534516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] = xy[1] + mScrollY - v.getTop();
13544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       cachedInverseMatrix.mapPoints(xy);
13554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
13564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
13584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
13594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from this CellLayout's coordinate space to
13604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * the parent View's coordinate space. The argument xy is modified with the return result.
13614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
13624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
13634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromChildToSelf(View v, float[] xy) {
13644516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       v.getMatrix().mapPoints(xy);
13654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] -= (mScrollX - v.getLeft());
13664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] -= (mScrollY - v.getTop());
13674516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
13684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    static private float squaredDistance(float[] point1, float[] point2) {
13704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceX = point1[0] - point2[0];
13714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceY = point2[1] - point2[1];
13724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return distanceX * distanceX + distanceY * distanceY;
13730280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
13740280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
13754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
13764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
13774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Returns true if the passed CellLayout cl overlaps with dragView
13784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
13794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
13804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    boolean overlaps(CellLayout cl, DragView dragView,
13814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
13824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the coordinates of the item being dragged to the CellLayout's coordinates
13834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemTopLeft = mTempDragCoordinates;
13844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[0] = dragViewX + dragView.getScaledDragRegionXOffset();
13854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[1] = dragViewY + dragView.getScaledDragRegionYOffset();
13864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
13874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getScaledDragRegionWidth();
13884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getScaledDragRegionHeight();
13894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the dragged item's top left coordinates
13914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // to the CellLayout's local coordinates
13924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
13934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
13944516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
13954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
13964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
13974516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the dragged item's bottom right coordinates
13984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // to the CellLayout's local coordinates
13994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
14004516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
14014516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
14024516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
14034516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
14044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float overlap = (overlapRegionRight - overlapRegionLeft) *
14054516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                         (overlapRegionBottom - overlapRegionTop);
14064516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (overlap > 0) {
14074516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    return true;
14084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                }
14094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka             }
14104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        }
14114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return false;
14124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    }
1413a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
14144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
14154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
14164516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * This method returns the CellLayout that is currently being dragged to. In order to drag
14174516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
14184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
14194516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
14204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Return null if no CellLayout is currently being dragged over
14214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
14224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
14234516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private CellLayout findMatchingPageForDragOver(
14244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            DragView dragView, int originX, int originY, int offsetX, int offsetY) {
14254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which ones overlap
14264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // with the item being dragged and then choose the one that's closest to the touch point
1427a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
1428a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
14290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float smallestDistSoFar = Float.MAX_VALUE;
14304516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
1431a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
1432a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
1433a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
14344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            final float[] touchXy = mTempTouchCoordinates;
14354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[0] = originX + offsetX;
14364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[1] = originY + offsetY;
1437a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
14384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the touch coordinates to the CellLayout's local coordinates
14394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // If the touch point is within the bounds of the cell layout, we can return immediately
14400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cl.getMatrix().invert(mTempInverseMatrix);
14414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
14424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
14434516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
14444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
14454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                return cl;
14464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
14474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
14484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
14494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Get the center of the cell layout in screen coordinates
14504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
14514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[0] = cl.getWidth()/2;
14524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[1] = cl.getHeight()/2;
14534516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                mapPointFromChildToSelf(cl, cellLayoutCenter);
14544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
14554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[0] = originX + offsetX;
14564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[1] = originY + offsetY;
14574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
14584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Calculate the distance between the center of the CellLayout
14594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // and the touch point
14604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float dist = squaredDistance(touchXy, cellLayoutCenter);
14614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
14624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (dist < smallestDistSoFar) {
14630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    smallestDistSoFar = dist;
1464a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
1465a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
14664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
1467a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1468a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
1469a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
1470a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1471440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1472440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
1473d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // When touch is inside the scroll area, skip dragOver actions for the current screen
1474d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mInScrollArea) {
1475d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            CellLayout layout;
1476d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originX = x - xOffset;
1477d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originY = y - yOffset;
1478d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mIsSmall || mIsInUnshrinkAnimation) {
1479d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = findMatchingPageForDragOver(
1480d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        dragView, originX, originY, xOffset, yOffset);
1481d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1482d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1483d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1484d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(false);
1485d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1486d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
1487d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1488d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(true);
1489d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1490d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1491d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            } else {
1492d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = getCurrentDropLayout();
1493d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1494d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                final ItemInfo item = (ItemInfo)dragInfo;
1495d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (dragInfo instanceof LauncherAppWidgetInfo) {
1496d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
1497d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1498d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (widgetInfo.spanX == -1) {
1499d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        // Calculate the grid spans needed to fit this widget
1500d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int[] spans = layout.rectToCell(
1501d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                widgetInfo.minWidth, widgetInfo.minHeight, null);
1502d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanX = spans[0];
1503d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanY = spans[1];
1504d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1505d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1506a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1507d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (source instanceof AllAppsPagedView) {
1508d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // This is a hack to fix the point used to determine which cell an icon from
1509d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // the all apps screen is over
1510d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (item != null && item.spanX == 1 && layout != null) {
1511d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
1512d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1513d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        originX += dragRegionLeft - dragView.getDragRegionLeft();
1514d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
1515d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            dragView.setDragRegion(dragView.getDragRegionLeft(),
1516d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionTop(),
1517d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    layout.getCellWidth(),
1518d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionHeight());
1519d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        }
1520d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1521a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
15221262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1523d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1524d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1525d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.onDragExit();
1526d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1527a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                    layout.onDragEnter();
1528d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
15291262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                }
15306569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1531d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // only visualize the drop locations for moving icons within the home screen on
1532d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // tablet on phone, we also visualize icons dragged in from All Apps
1533d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if ((!LauncherApplication.isScreenXLarge() || source == this)
1534d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        && mDragTargetLayout != null) {
1535d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    final View child = (mDragInfo == null) ? null : mDragInfo.cell;
1536d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
1537d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
1538d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
1539d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            localOriginX, localOriginY, item.spanX, item.spanY);
1540d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
15411262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            }
1542976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
154331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
154431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1545aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
1546aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
15476569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
15480280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mDragTargetLayout.onDragExit();
15496569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
15501262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mIsPageMoving) {
15511262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
15521b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            mInDragMode = false;
15531262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
155408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        clearAllHovers();
155531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
155631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1557aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1558aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
155931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
156031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1561aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
15622b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
15632b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
15642b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
15652b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
15662b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
15672b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
15682b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
15692b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
15702b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
15712b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
15720280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
157355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung            onDropExternal(-1, -1, dragInfo, cl, false);
15742b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
15752b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
15760280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mLauncher.showOutOfSpaceMessage();
15772b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
15782b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
15792b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
15800280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    // Drag from somewhere else
15814be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // NOTE: This can also be called when we are outside of a drag event, when we want
15824be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // to add an item to one of the workspace screens.
1583aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1584aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
15850280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int screen = indexOfChild(cellLayout);
15860280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (dragInfo instanceof PendingAddItemInfo) {
15870280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
15880280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // When dragging and dropping from customization tray, we deal with creating
15890280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // widgets/shortcuts/folders in a slightly different way
15900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            int[] touchXY = new int[2];
15910280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[0] = x;
15920280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[1] = y;
15930280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            switch (info.itemType) {
15940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
159555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) info, screen, touchXY);
15960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
15970280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
15980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
15990280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
16000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
16010280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
16020280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
16030280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                default:
16040280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    throw new IllegalStateException("Unknown item type: " + info.itemType);
16050280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
16060280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
160718014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
16080280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return;
16090280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
16100280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
16110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        // This is for other drag/drop cases, like dragging from All Apps
161231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
161331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1614af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
161531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
161631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
161731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
161831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1619e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
162031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1621aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
162231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1623aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1624aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
162531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
162631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
162731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
16280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    cellLayout, ((UserFolderInfo) info));
1629af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
163031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
16310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            throw new IllegalStateException("Unknown item type: " + info.itemType);
163231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
163331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16346569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
16356569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
16360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
16376569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
16387ded67cd64153cd41bb133a6aab11b3254b4a5d9Michael Jurka            mTargetCell = findNearestVacantArea(x, y, 1, 1, null, cellLayout, mTargetCell);
1639aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1640aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1641aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
164218014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
16436569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
164431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1645af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
16460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1647aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1648af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
164931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1650aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
165170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
165270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
165370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
165470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
165570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
1656d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // if we're currently small, use findMatchingPageForDragOver instead
1657d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mIsSmall) return null;
16580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
165970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
166070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
166131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
166270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
16630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * Return the current CellInfo describing our current drag; this method exists
16640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * so that Launcher can sync this object with the correct info when the activity is created/
16650280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * destroyed
16660280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     *
16670280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     */
16680280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public CellLayout.CellInfo getDragInfo() {
16690280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return mDragInfo;
16700280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
16710280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
16720280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    /**
167370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * {@inheritDoc}
167470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
167570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    public boolean acceptDrop(DragSource source, int x, int y,
167600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
1677d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout == null) {
1678d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // cancel the drag if we're not over a screen at time of drop
1679d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            return false;
16800280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1681d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1682c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final CellLayout.CellInfo dragCellInfo = mDragInfo;
1683c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1684c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
16854c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1686c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
16874c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1688d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
16890e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return true;
16900e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        } else {
16910280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mLauncher.showOutOfSpaceMessage();
16920e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return false;
16930e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        }
169470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1695aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
169670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
169770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
169870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
16996a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka    private int[] findNearestVacantArea(int pixelX, int pixelY,
170070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
17016569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
17025f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
17035f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelY = pixelY - (layout.getTop() - mScrollY);
17046569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
170570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
17060280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return layout.findNearestVacantArea(
1707fc9f07d42511231a26fa182c32e2efaa0f41d478Michael Jurka                localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
170870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1709aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
17108f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
17118f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
17128f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
17138f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
17140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
17158f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
17168f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
171731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
171831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
171931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
172031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
172100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
172200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
172331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
172431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
172531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1726aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
172731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
172831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
172931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
173000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
173100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
173200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1733aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
173431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1735ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
1736ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            ((CellLayout) getChildAt(mDragInfo.screen)).onDropAborted(mDragInfo.cell);
173731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
173831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragOutline = null;
174031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
174131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
174231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
17440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return true;
17450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
17460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
17470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
17480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
17490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
17500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
17510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
17520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
17530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
175431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
1755c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
17560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
175731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
175831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
175931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
176131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
1762c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
17630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
176431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
176531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1766138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
17671262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
17681262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onEnterScrollArea(int direction) {
1769d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
1770d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = true;
1771d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            final int screen = getCurrentPage() + ((direction == DragController.SCROLL_LEFT) ? -1 : 1);
1772d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (0 <= screen && screen < getChildCount()) {
1773d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                ((CellLayout) getChildAt(screen)).setHover(true);
1774d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
17751262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1776d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mDragTargetLayout != null) {
1777d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout.onDragExit();
1778d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout = null;
1779d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
17801262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
17811262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
17821262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
178308ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    private void clearAllHovers() {
178408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        final int childCount = getChildCount();
178508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        for (int i = 0; i < childCount; i++) {
178608ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            ((CellLayout) getChildAt(i)).setHover(false);
178708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        }
178808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    }
178908ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
17901262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
17911262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onExitScrollArea() {
1792d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mInScrollArea) {
1793d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = false;
179408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            clearAllHovers();
17951262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
17961262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
17971262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
179831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1799dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
180031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
180131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
180231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
180331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
180431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
180531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
180631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
180731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
1808aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
180931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
181031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
181131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
181231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
181331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
181431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
181531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
181631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
181731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
181831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
181931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
182031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
182131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
182231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
182331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
182431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
182531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
182631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
182731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
182831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
182931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
183031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
183131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
183231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
183364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
1834dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
18355c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
1836629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
1837574d20ec84551370987dde530c27ec493bdef564Romain Guy
183864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
183964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
184064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
184164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
184264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
184364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
1844dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
184531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1846629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1847629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
1848629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
1849629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
1850629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
1851629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
1852aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1853629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
1854629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1855629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
1856629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
1857aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
18580589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
18590589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
1860629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
1861629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
1862aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
186364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
186464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
186564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
186664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
186764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
186864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
186964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1870629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1871629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
1872629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
18730589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
18740589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
1875629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
1876629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
1877aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1878629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
18790589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
1880629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
1881629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
1882aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
188364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
188464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
188564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
188664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
188773013bf94f49ffbacba2b8300f6a2dd4eeebbd13Brad Fitzpatrick                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
188864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
188964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
189064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
1891629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
1892629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1893aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1894629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
1895629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
1896629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
1897aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
1898aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
1899629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1900629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
1901629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
1902629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
1903629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
1904629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
1905629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1906f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
190764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
190864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
190964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1910aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
191164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
191264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1913629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1914629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
1915629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
1916629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
1917629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
1918e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
191964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
192064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
192164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1922aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
192364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
192464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1925629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1926574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
1927574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1928aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1929629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
1930629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1931629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
1932629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
1933629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
1934629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
1935629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
1936574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1937aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1938629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
1939629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
1940629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
19415c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
194231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
1943629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
194431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
194531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1946f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
194764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
1948dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
1949dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
1950f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1951f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
1952f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
1953f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
1954f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
19550589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
19560589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
1957f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
1958f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
1959f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
1960f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
1961f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
1962f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
196364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
196464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
1965aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
196664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
196764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
196864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
196964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
197064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
197164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
197264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
197364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
1974f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
1975f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
1976f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
1977f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
1978f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
1979f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
198014f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
1981c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1982c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
1983c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        } else if (animate) {
1984c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            snapToPage(mDefaultPage);
1985c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
19860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
1987c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
19880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
198931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
199031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19918a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
19928a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
19938a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
19940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
19950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
19968a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
19978a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
19980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
19990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
20000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
200131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
20020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
20030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
200431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
20050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
200631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
2007