Workspace.java revision a34abf8c781485b788fddacb352d586bffca886c
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
1968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport java.util.ArrayList;
2068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport java.util.HashSet;
2168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport java.util.List;
22495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell
23580e27748137ff08599aa719d106b31215a28353Winson Chungimport android.R.integer;
240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.Animator;
2568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport android.animation.Animator.AnimatorListener;
26b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.AnimatorSet;
270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.ObjectAnimator;
280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.PropertyValuesHolder;
29cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.animation.TimeInterpolator;
30cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.animation.ValueAnimator;
31cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.animation.ValueAnimator.AnimatorUpdateListener;
3268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport android.app.AlertDialog;
338f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.app.WallpaperManager;
34629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetManager;
35629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
36a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.content.ClipData;
37a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.content.ClipDescription;
38495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.ComponentName;
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent;
41495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.pm.PackageManager;
425c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.content.pm.ProviderInfo;
437247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.content.res.Resources;
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.TypedArray;
454be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Bitmap;
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
47a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.graphics.Matrix;
48a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.graphics.Paint;
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
50a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.graphics.RectF;
514be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Region.Op;
52f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.graphics.drawable.Drawable;
535c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.net.Uri;
54956091ba7863bd72086275e61084864994dd6fa7Joe Onoratoimport android.os.IBinder;
55495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcelable;
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
57291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandlerimport android.util.Log;
58580e27748137ff08599aa719d106b31215a28353Winson Chungimport android.util.Pair;
59a34abf8c781485b788fddacb352d586bffca886cWinson Chungimport android.view.Display;
60a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.DragEvent;
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
6231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
63cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.view.animation.DecelerateInterpolator;
64f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
65a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.widget.Toast;
6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport com.android.launcher.R;
6868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
69edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
7031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
73aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
7431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
76dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
77e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
783a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
80dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
81dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
82dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
83a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
84f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    // Y rotation to apply to the workspace screens
85f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final float WORKSPACE_ROTATION = 12.5f;
86a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
87a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // These are extra scale factors to apply to the mini home screens
88a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // so as to achieve the desired transform
891b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private static final float EXTRA_SCALE_FACTOR_0 = 0.972f;
90a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
911b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private static final float EXTRA_SCALE_FACTOR_2 = 1.10f;
92a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
93f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DELAY = 300;
94f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DURATION = 300;
95f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_IN_DURATION = 100;
96f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // These animators are used to fade the background
98472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeInAnimation;
99472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeOutAnimation;
100f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private float mBackgroundAlpha = 0;
101f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
1028f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
103aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    private boolean mPageMoving = false;
10721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
112aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
11370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
11470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
11570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
11670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1186569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
1196569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
1206569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
1216569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
1226569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
1240589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
12500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
126aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1274516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // These are temporary variables to prevent having to allocate a new object just to
1284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
13070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
1310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private float[] mTempOriginXY = new float[2];
132a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
1334516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempTouchCoordinates = new float[2];
1344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempCellLayoutCenterCoordinates = new float[2];
135a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
1360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private Matrix mTempInverseMatrix = new Matrix();
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
138d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
139d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1418a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1428a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
143aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1441262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    // State variable that indicates whether the pages are small (ie when you're
145dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
146c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsSmall = false;
147c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsInUnshrinkAnimation = false;
148b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
1493e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private enum ShrinkPosition {
1503e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM_HIDDEN, SHRINK_TO_BOTTOM_VISIBLE };
1513e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ShrinkPosition mShrunkenState;
152883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    private boolean mWaitingToShrink = false;
153883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    private ShrinkPosition mWaitingToShrinkPosition;
1543c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka    private AnimatorSet mAnimator;
155dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
1561262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    private boolean mInScrollArea = false;
1571b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private boolean mInDragMode = false;
1581262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1598e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
1604be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap mDragOutline = null;
1618e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final Rect mTempRect = new Rect();
1628e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final int[] mTempXY = new int[2];
1634be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
164cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private ValueAnimator mDropAnim = null;
165cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f);
166cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private View mDropView = null;
167cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private int[] mDropViewPos = new int[] { -1, -1 };
168cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
169a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    // Paint used to draw external drop outline
170a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    private final Paint mExternalDragOutlinePaint = new Paint();
171a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1728ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy    /** Used to trigger an animation as soon as the workspace stops scrolling. */
1738ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy    private Animator mAnimOnPageEndMoving = null;
1748ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
17731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
19231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
19331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1955f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
1965f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
1975f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFadeInAdjacentScreens = false;
1985f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2008f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
201aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
202aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
203aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
204d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
205d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
2060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
209d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
2100d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
2110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
21231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
21331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
21431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
2180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
2190589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
2200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
2210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
2220589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
2230589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
224a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        mExternalDragOutlinePaint.setAntiAlias(true);
225cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        setWillNotDraw(false);
22631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2273c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        mUnshrinkAnimationListener = new LauncherAnimatorListenerAdapter() {
2283c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            @Override
229c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            public void onAnimationStart(Animator animation) {
230c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = true;
231c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            }
2323c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            @Override
2333c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            public void onAnimationEndOrCancel(Animator animation) {
234c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = false;
235dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
236dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
2370142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
241f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected int getScrollMode() {
242f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        if (LauncherApplication.isScreenXLarge()) {
243f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.QUINTIC_MODE;
244f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        } else {
245f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.OVERSHOOT_MODE;
246f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
247f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
248f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
249f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
25031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
26131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
26321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
27131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
28121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
28231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
29021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
29131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
29231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
29631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
3010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
302aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
303aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
304aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
305aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
31031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
312dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
313dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
315dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
3160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
3170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
3190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
320aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
321aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
322aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
323aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
32631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
32731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3310142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
3320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
3380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
3420142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
3430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
35031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
35931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
36031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
361aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
362aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
363aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
364aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
36931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
37031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
37131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
37231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
37331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
37431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
37531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
37831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
379291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
380291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
381291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
38231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
38331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
38931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
39031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
39231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
39331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
394aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3956569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
396845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
397f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        boolean markCellsAsOccupied = !(child instanceof Folder);
398f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
399aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
400aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
4016569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
402aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
403aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
404aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
40531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
4060d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
40731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
40831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
40900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
410aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
41100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
41231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
41331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
414dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
415dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
416c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4172b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
41896226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
41921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        } else if (!mPageMoving) {
42021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            if (v == getChildAt(mCurrentPage - 1)) {
42121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage - 1);
42221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
42321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            } else if (v == getChildAt(mCurrentPage + 1)) {
42421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage + 1);
42521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
42621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            }
427dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
428dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
4290e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
4300e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
431ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen    protected void onWindowVisibilityChanged (int visibility) {
432ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen        mLauncher.onWindowVisibilityChanged(visibility);
433ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen    }
434ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen
4355f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4365f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
437c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4385f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4395f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4405f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4415f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
4425f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4435f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4445f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4455f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
446c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4475f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4485f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4495f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4505f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.onInterceptTouchEvent(ev);
4515f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4525f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4531adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    @Override
4541adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    protected void determineScrollingStart(MotionEvent ev) {
4551adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) super.determineScrollingStart(ev);
4561adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    }
4571adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka
4581262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageBeginMoving() {
4590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
4600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
46116fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage, mNextPage);
4620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
4640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
46516fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
46631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
467f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        showOutlines();
46821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = true;
46931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
47031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4711262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageEndMoving() {
47216fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        clearChildrenCache();
4731262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        // Hide the outlines, as long as we're not dragging
4741262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mDragController.dragging()) {
4751262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
4761262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
4778ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        // Check for an animation that's waiting to be started
4788ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (mAnimOnPageEndMoving != null) {
4798ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving.start();
4808ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving = null;
4818ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
4828ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
48321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = false;
4840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
4850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
4870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
4880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
4890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
4910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
4920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
4930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
5000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
5010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
5020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5038f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
504798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
505798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
506798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
507798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
50886f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
50986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
51086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
51186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
51286f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
51386f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
51486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
51586f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
51686f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
517956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
5188f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
519aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
520f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void showOutlines() {
5213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
5223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
5233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
524472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
525472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
5263e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeInAnimation.start();
5273e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
528f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
529f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
530f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void hideOutlines() {
5313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
5323e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
5333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
534472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
535472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
5363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
5373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.start();
5383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
539f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
540f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
541f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void setBackgroundAlpha(float alpha) {
542f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        mBackgroundAlpha = alpha;
543f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
544f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
545f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            cl.setBackgroundAlpha(alpha);
546f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
547f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
548f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
549f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public float getBackgroundAlpha() {
550f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        return mBackgroundAlpha;
551f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
552f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
553f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
554f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected void screenScrolled(int screenCenter) {
55521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        final int halfScreenSize = getMeasuredWidth() / 2;
55621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
5571b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
5581b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            if (cl != null) {
5591b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                int totalDistance = cl.getMeasuredWidth() + mPageSpacing;
56021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int delta = screenCenter - (getChildOffset(i) -
56121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                        getRelativeChildOffset(i) + halfScreenSize);
562f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
563ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen                float scrollProgress = delta / (totalDistance * 1.0f);
56421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.min(scrollProgress, 1.0f);
56521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.max(scrollProgress, -1.0f);
566f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
567ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen                cl.setBackgroundAlphaMultiplier(Math.abs(scrollProgress));
5681b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
56921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float rotation = WORKSPACE_ROTATION * scrollProgress;
5701b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                cl.setRotationY(rotation);
571f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            }
572f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
573f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
574f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
57500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
57600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
577956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
57800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
57900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
58000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
58131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
58228750fba6a2d141eb9a1e566718c17236030b815Michael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
5830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
584aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
58579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
58679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
587883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (mWaitingToShrink) {
588883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            shrink(mWaitingToShrinkPosition, false);
589883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrink = false;
59079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
59179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
592aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
593aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
594aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
5950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
596aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
59731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
59831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
6000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
601c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
6020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
6030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
6040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
6050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
6060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
6070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
6090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
6100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
6110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
612cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
6130207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            final int width = getWidth();
6140207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            final int height = getHeight();
6150207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
6160207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            // In portrait orientation, draw the glowing edge when dragging to adjacent screens
6170207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            if (mInScrollArea && (height > width)) {
6180207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final int pageHeight = getChildAt(0).getHeight();
6190207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
6200207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                // This determines the height of the glowing edge: 90% of the page height
6210207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final int padding = (int) ((height - pageHeight) * 0.5f + pageHeight * 0.1f);
6220207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
6230207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final CellLayout leftPage = (CellLayout) getChildAt(mCurrentPage - 1);
6240207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final CellLayout rightPage = (CellLayout) getChildAt(mCurrentPage + 1);
6250207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
6260207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                if (leftPage != null && leftPage.getHover()) {
6270207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    final Drawable d = getResources().getDrawable(R.drawable.page_hover_left);
6280207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    d.setBounds(mScrollX, padding, mScrollX + d.getIntrinsicWidth(), height - padding);
6290207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    d.draw(canvas);
6300207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                } else if (rightPage != null && rightPage.getHover()) {
6310207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    final Drawable d = getResources().getDrawable(R.drawable.page_hover_right);
6320207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    d.setBounds(mScrollX + width - d.getIntrinsicWidth(), padding, mScrollX + width, height - padding);
6330207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    d.draw(canvas);
6340207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                }
6350207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            }
6360207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
637cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDropView != null) {
6388ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                // We are animating an item that was just dropped on the home screen.
6398ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                // Render its View in the current animation position.
640cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.save(Canvas.MATRIX_SAVE_FLAG);
641cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final int xPos = mDropViewPos[0] - mDropView.getScrollX();
642cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final int yPos = mDropViewPos[1] - mDropView.getScrollY();
643cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.translate(xPos, yPos);
644cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropView.draw(canvas);
645cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.restore();
646cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
64731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
64831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
64931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
65031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
65131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
652678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
65331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
65431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
65531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
65631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
6570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
65831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
65931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
66031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
66131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
66231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
66331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
664c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
665678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
66631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
6670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
66831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
6690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
6700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
67131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
67231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
67331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
67431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
67531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
6767bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
6777bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
67854dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
67954dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
6806b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
6817bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
6827bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
6837bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
6847bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
6857bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
6867bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
6870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
6880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
6890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
6900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
6910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
6923a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
693aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
694dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
695fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
6970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
698fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
70031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
70131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
70231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
70331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
70431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
70531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
70631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
707dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
708dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
70931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
71031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
71131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
71231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
71331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
71431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
71531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
7162bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
7172bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
7182bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
7192bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
7202bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
7213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            setCurrentPage(mCurrentPage);
7227c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
72331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
72431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
72631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
727aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
72801f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
72901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
73001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
73101f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
7326b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
7330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
73401f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
73501f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
73601f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
7370142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
738213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
739213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
740213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
74179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
74279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
74379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
74479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
745883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, animated);
746213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
747213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
748a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float getYScaleForScreen(int screen) {
749a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int x = Math.abs(screen - 2);
750a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
751a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // TODO: This should be generalized for use with arbitrary rotation angles.
752a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        switch(x) {
753a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 0: return EXTRA_SCALE_FACTOR_0;
754a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 1: return EXTRA_SCALE_FACTOR_1;
755a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 2: return EXTRA_SCALE_FACTOR_2;
756a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
757a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        return 1.0f;
758a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
759a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
760dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
7610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
762883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (mFirstLayout) {
763883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
764883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
765883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
766883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // to get our width so we can layout the mini-screen views correctly
767883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrink = true;
768883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrinkPosition = shrinkPosition;
769883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            return;
770883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        }
771dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
7723e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        mShrunkenState = shrinkPosition;
7733e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7743e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        // Stop any scrolling, move to the current page right away
775a997ac26664befbd0d5b172e36ef9e8b2c63b435Michael Jurka        setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage);
7763e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
7773e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7785f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // we intercept and reject all touch events when we're small, so be sure to reset the state
7795f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mTouchState = TOUCH_STATE_REST;
7805f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mActivePointerId = INVALID_POINTER;
7815f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
7821b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
783ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen        if (currentPage.getBackgroundAlphaMultiplier() < 1.0f) {
784ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen            currentPage.setBackgroundAlpha(0.0f);
785ddb821981e0919bbd3b4c9a2b6aa1811d6c86bb6Adam Cohen        }
7861b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        currentPage.setBackgroundAlphaMultiplier(1.0f);
7871b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
7887247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
789dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
790213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
7910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
7930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
7940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
7950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
7970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
798a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
799dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
800dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
801a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
802213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
803df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        boolean isPortrait = getMeasuredHeight() > getMeasuredWidth();
804df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        float newY = (isPortrait ?
805ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginPortrait) :
806ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginLandscape));
8073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float finalAlpha = 1.0f;
8083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float extraShrinkFactor = 1.0f;
8093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
8103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             newY = screenHeight - newY - scaledPageHeight;
8113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
8123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // We shrink and disappear to nothing in the case of all apps
8143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // (which is when we shrink to the bottom)
8150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
8167da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung            finalAlpha = 0.25f;
8170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
818b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            newY = screenHeight / 2 - scaledPageHeight / 2;
819b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            finalAlpha = 1.0f;
820b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_TOP) {
821ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung            newY = (isPortrait ?
822ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginPortrait) :
823ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginLandscape));
824213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
825dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
826dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
827dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
828dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
829dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
8300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
831a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
832a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // We are going to scale about the center of the view, so we need to adjust the positions
833a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // of the views accordingly
834a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newX -= (pageWidth - scaledPageWidth) / 2.0f;
835a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newY -= (pageHeight - scaledPageHeight) / 2.0f;
8363c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka
8373c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        if (mAnimator != null) {
8383c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator.cancel();
8393c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        }
8403c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        mAnimator = new AnimatorSet();
841dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
842dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
843a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
844f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            float rotation = (-i + 2) * WORKSPACE_ROTATION;
845a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
846a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleY = getYScaleForScreen(i);
847a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
84879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
8497247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
850472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(cl,
851472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("x", newX),
852472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("y", newY),
853472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleX",
8543e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleX * extraShrinkFactor),
855472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleY",
8563e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor),
857472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha),
858472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("alpha", finalAlpha),
859472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("rotationY", rotation));
860472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.setDuration(duration);
8613c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.playTogether(anim);
86279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
86379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
86479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
865883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setScaleX(SHRINK_FACTOR * rotationScaleX * extraShrinkFactor);
866883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setScaleY(SHRINK_FACTOR * rotationScaleY * extraShrinkFactor);
867883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setBackgroundAlpha(finalAlpha);
8683e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                cl.setAlpha(finalAlpha);
869a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                cl.setRotationY(rotation);
87079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
871dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
872a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            newX += scaledPageWidth + extraScaledSpacing;
873dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
8743c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        if (animated) {
8753c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator.start();
8763c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        }
877dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
878dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
879dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
8803e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
8823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
8833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkPosition state, int spanX, int spanY) {
8873e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, true, spanX, spanY);
8883e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8893e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsHelper(
8913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ShrinkPosition state, boolean isDragHappening, int spanX, int spanY) {
8923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        final int screenCount = getChildCount();
8933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        for (int i = 0; i < screenCount; i++) {
8943e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
8953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            switch (state) {
8973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_TOP:
8983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8993e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        boolean showDropHighlight = i == mCurrentPage;
9003e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        cl.setAcceptsDrops(showDropHighlight);
9013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        break;
9023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
9033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // otherwise, fall through below and mark non-full screens as accepting drops
9043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_HIDDEN:
9053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_VISIBLE:
9063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
9073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // even if a drag isn't happening, we don't want to show a screen as
9083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // accepting drops if it doesn't have at least one free cell
9093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanX = 1;
9103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanY = 1;
9113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
9123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // the page accepts drops if we can find at least one empty spot
9133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
9143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    break;
9153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                default:
9163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                     throw new RuntimeException(
9173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkPosition");
9183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
9193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
9203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
9223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    /*
9233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
9243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
9253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
9263e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
9273e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * These methods mark the appropriate pages as accepting drops (which alters their visual
9283e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * appearance) and, if the pages are hidden, makes them visible.
9293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
9303e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     */
9313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemSpans(int spanX, int spanY) {
9323e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsDuringDrag(mShrunkenState, spanX, spanY);
9333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
9343e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE, true);
9353e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
9363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
9383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemMinSize(int minWidth, int minHeight) {
9393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        int[] spanXY = CellLayout.rectToCell(getResources(), minWidth, minHeight, null);
9403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        onDragStartedWithItemSpans(spanXY[0], spanXY[1]);
9413e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9423e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
9433e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
9443e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // never dragged over
9453e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStopped() {
9463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
9477da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
9487da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, true);
9497da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung        }
9503e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9513e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
952dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
9532b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
9540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
9554cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
9564cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
9574cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
9580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
9594cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
9604cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
9610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
9624cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
9634cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
96421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    @Override
96521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    protected boolean handlePagingClicks() {
96621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        return true;
96721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    }
96821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
9690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
970b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
9715f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
9725f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int delta = newX - mScrollX;
9734cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
974b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
975b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
976b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
977b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
978b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
9790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
980c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            unshrink();
981b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
982dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
983dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
9844cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
9854cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
9864cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
9874cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
9884cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
989b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
990c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mIsSmall = false;
9913c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            if (mAnimator != null) {
9923c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.cancel();
9933c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            }
9943c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator = new AnimatorSet();
995b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
9964cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
9974cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
998b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
9997247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
10005f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
1001f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                float rotation = 0.0f;
1002f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
1003f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (i < mCurrentPage) {
1004f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = WORKSPACE_ROTATION;
1005f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                } else if (i > mCurrentPage) {
1006f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = -WORKSPACE_ROTATION;
1007f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                }
1008f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
10094cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
10103c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                    mAnimator.playTogether(
1011472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationX", 0.0f).setDuration(duration),
1012472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationY", 0.0f).setDuration(duration),
1013472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleX", 1.0f).setDuration(duration),
1014472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleY", 1.0f).setDuration(duration),
1015472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "backgroundAlpha", 0.0f).setDuration(duration),
1016472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "alpha", finalAlphaValue).setDuration(duration),
1017472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "rotationY", rotation).setDuration(duration));
10184cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
10194cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
10204cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
10214cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
10224cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
10235f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setBackgroundAlpha(0.0f);
1024f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setAlpha(finalAlphaValue);
1025f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setRotationY(rotation);
10264cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
1027b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
1028c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            if (animated) {
1029c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // If we call this when we're not animated, onAnimationEnd is never called on
1030c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // the listener; make sure we only use the listener when we're actually animating
10313c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.addListener(mUnshrinkAnimationListener);
10323c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.start();
1033c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            }
1034dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
1035dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
1036dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
10374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
10384be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Draw the View v into the given Canvas.
10394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     *
10404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param v the view to draw
10414be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param destCanvas the canvas to draw on
10424be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param padding the horizontal and vertical padding to use when drawing
10434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
10444be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private void drawDragView(View v, Canvas destCanvas, int padding) {
10454be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Rect clipRect = mTempRect;
10464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.getDrawingRect(clipRect);
10474be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10484be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // For a TextView, adjust the clip rect so that we don't include the text label
10494be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        if (v instanceof TextView) {
1050bbc60d8e79416e37cbede55c159bf6aaa6c171d5Winson Chung            final TextView tv = (TextView) v;
1051bbc60d8e79416e37cbede55c159bf6aaa6c171d5Winson Chung            clipRect.bottom = clipRect.top + tv.getCompoundPaddingTop() - 1;
10524be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        }
10534be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10544be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // Draw the View into the bitmap.
10554be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
10564be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // they set scrollX and scrollY to large values to achieve centered text
10574be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.save();
10594be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
10604be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.clipRect(clipRect, Op.REPLACE);
10614be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.draw(destCanvas);
10624be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.restore();
10634be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10644be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10654be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
10664be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
10674be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
10684be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
10694be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {
10704be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
10714be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
10724be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
10734be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10744be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
10754be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
10764be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
10774be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10784be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
10794be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10804be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10814be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
1082a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * Creates a drag outline to represent a drop (that we don't have the actual information for
1083a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * yet).  May be changed in the future to alter the drop outline slightly depending on the
1084a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * clip description mime data.
1085a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     */
1086a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    private Bitmap createExternalDragOutline(Canvas canvas, int padding) {
1087a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        Resources r = getResources();
1088a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int outlineColor = r.getColor(R.color.drag_outline_color);
1089a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int iconWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
1090a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int iconHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height);
1091a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int rectRadius = r.getDimensionPixelSize(R.dimen.external_drop_icon_rect_radius);
1092a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int inset = (int) (Math.min(iconWidth, iconHeight) * 0.2f);
1093a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final Bitmap b = Bitmap.createBitmap(
1094a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                iconWidth + padding, iconHeight + padding, Bitmap.Config.ARGB_8888);
1095a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1096a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        canvas.setBitmap(b);
1097a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        canvas.drawRoundRect(new RectF(inset, inset, iconWidth - inset, iconHeight - inset),
1098a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                rectRadius, rectRadius, mExternalDragOutlinePaint);
1099a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
1100a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1101a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        return b;
1102a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
1103a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1104a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
11054be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to show when the given View is being dragged around.
11064be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
11074be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
11084be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
11094be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
11104be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
11114be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                mDragOutline.getWidth(), mDragOutline.getHeight(), Bitmap.Config.ARGB_8888);
11124be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11134be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
11144be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.drawBitmap(mDragOutline, 0, 0, null);
11154be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
11168e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
11174be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11184be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
11194be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
11204be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
112131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
112231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
1123aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
112431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
11257984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
112631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
112731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
1128aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
112931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
11300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
1131aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
113208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        CellLayout current = getCurrentDropLayout();
113331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
113431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
1135cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        child.setVisibility(View.GONE);
11364be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.clearFocus();
11384be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.setPressed(false);
11394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Canvas canvas = new Canvas();
11414be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11428e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        // We need to add extra padding to the bitmap to make room for the glow effect
11438e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
11448e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy
11454be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The outline is used to visualize where the item will land if dropped
11468e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mDragOutline = createDragOutline(child, canvas, bitmapPadding);
11474be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11484be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The drag bitmap follows the touch point around on the screen
11498e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final Bitmap b = createDragBitmap(child, canvas, bitmapPadding);
11504be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11514be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpWidth = b.getWidth();
11524be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpHeight = b.getHeight();
11534be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.getLocationOnScreen(mTempXY);
11544be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
11554be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
11564be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
11574be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                child.getTag(), DragController.DRAG_ACTION_MOVE, null);
11584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        b.recycle();
115931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
116031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
11620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            boolean insertAtFirst, int intersectX, int intersectY) {
11630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
11640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
116531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11660280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final int[] cellXY = new int[2];
11670280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
11680280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
11690280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
11700280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
11710280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellXY[0], cellXY[1]);
117231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
117331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1174ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    private void setPositionForDropAnimation(
1175ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            View dragView, int dragViewX, int dragViewY, View parent, View child) {
1176ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
1177ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1178ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // Based on the position of the drag view, find the top left of the original view
1179ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
1180ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
1181ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewX -= getResources().getInteger(R.integer.config_dragViewOffsetX);
1182ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewY -= getResources().getInteger(R.integer.config_dragViewOffsetY);
1183ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1184cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Set its old pos (in the new parent's coordinates); it will be animated
1185cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // in animateViewIntoPosition after the next layout pass
1186ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldX = viewX - (parent.getLeft() - mScrollX);
1187ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldY = viewY - (parent.getTop() - mScrollY);
1188ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    }
11890280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
1190cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    public void animateViewIntoPosition(final View view) {
1191cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final CellLayout parent = (CellLayout) view.getParent();
1192cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
1193cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1194cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Convert the animation params to be relative to the Workspace, not the CellLayout
1195cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int fromX = lp.oldX + parent.getLeft();
1196cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int fromY = lp.oldY + parent.getTop();
1197cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1198cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int dx = lp.x - lp.oldX;
1199cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int dy = lp.y - lp.oldY;
1200cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1201cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Calculate the duration of the animation based on the object's distance
1202cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final float dist = (float) Math.sqrt(dx*dx + dy*dy);
1203cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final Resources res = getResources();
1204cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
12058ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        int duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
12068ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (dist < maxDist) {
12078ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            duration *= mQuintEaseOutInterpolator.getInterpolation(dist / maxDist);
12088ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
1209cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1210f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        if (mDropAnim != null) {
1211f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            // This should really be end(), but that will not be called synchronously,
1212f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            // so instead we use LauncherAnimatorListenerAdapter.onAnimationEndOrCancel()
1213f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            // and call cancel() here.
1214f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            mDropAnim.cancel();
1215f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        }
1216f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        mDropAnim = new ValueAnimator();
1217f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        mDropAnim.setInterpolator(mQuintEaseOutInterpolator);
1218cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1219f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        // The view is invisible during the animation; we render it manually.
1220f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        mDropAnim.addListener(new LauncherAnimatorListenerAdapter() {
1221f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            public void onAnimationStart(Animator animation) {
1222f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                // Set this here so that we don't render it until the animation begins
1223f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                mDropView = view;
1224f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            }
1225f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy
1226f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            public void onAnimationEndOrCancel(Animator animation) {
1227f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                if (mDropView != null) {
1228f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                    mDropView.setVisibility(View.VISIBLE);
1229f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                    mDropView = null;
1230cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                }
1231f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            }
1232f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        });
12338ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
1234cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.setDuration(duration);
1235cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.setFloatValues(0.0f, 1.0f);
1236cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.removeAllUpdateListeners();
1237cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.addUpdateListener(new AnimatorUpdateListener() {
1238cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            public void onAnimationUpdate(ValueAnimator animation) {
1239cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final float percent = (Float) animation.getAnimatedValue();
1240cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                // Invalidate the old position
1241cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                invalidate(mDropViewPos[0], mDropViewPos[1],
1242cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
1243cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1244cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropViewPos[0] = fromX + (int) (percent * dx + 0.5f);
1245cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropViewPos[1] = fromY + (int) (percent * dy + 0.5f);
1246cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                invalidate(mDropViewPos[0], mDropViewPos[1],
1247cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
1248cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1249cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        });
12508ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12518ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12528ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        view.setVisibility(View.INVISIBLE);
12538ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12548ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (!mScroller.isFinished()) {
12558ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving = mDropAnim;
12568ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        } else {
12578ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mDropAnim.start();
12588ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
1259cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    }
1260cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1261cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    /**
1262cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy     * {@inheritDoc}
1263cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy     */
1264cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    public boolean acceptDrop(DragSource source, int x, int y,
1265cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
1266cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1267cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // If it's an external drop (e.g. from All Apps), check if it should be accepted
1268cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        if (source != this) {
1269cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            // Don't accept the drop if we're not over a screen at time of drop
1270cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDragTargetLayout == null) {
1271cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                return false;
1272cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1273cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1274cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final CellLayout.CellInfo dragCellInfo = mDragInfo;
1275cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1276cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
1277cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1278cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
1279cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1280cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            // Don't accept the drop if there's no room for the item
1281cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (!mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
1282cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mLauncher.showOutOfSpaceMessage();
1283cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                return false;
1284cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1285cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        }
1286cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        return true;
1287cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    }
1288cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
128900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
129000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
1291ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1292ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originX = x - xOffset;
1293ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originY = y - yOffset;
1294ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1295c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
12960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
12970280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
12980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
1299d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
13000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
13010280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
1302a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1303c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
130431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
1305d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
1306ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
1307ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            final View cell = mDragInfo.cell;
1308cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDragTargetLayout != null) {
1309cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                // Move internally
1310cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mTargetCell = findNearestVacantArea(originX, originY,
1311cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
1312cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mTargetCell);
1313cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
13149438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                if (mTargetCell == null) {
13158ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                    snapToPage(mDragInfo.screen);
13169438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                } else {
13179438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    int screen = indexOfChild(mDragTargetLayout);
13189438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    if (screen != mDragInfo.screen) {
13199438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        // Reparent the view
13209438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        ((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell);
13219438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
13229438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                                mDragInfo.spanX, mDragInfo.spanY);
13239438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    }
1324cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
13259438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    // update the item's position after drop
13269438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    final ItemInfo info = (ItemInfo) cell.getTag();
13279438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
13289438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
13299438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    lp.cellX = mTargetCell[0];
13309438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    lp.cellY = mTargetCell[1];
13319438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
13329438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
13339438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy
13349438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    LauncherModel.moveItemInDatabase(mLauncher, info,
13359438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
13369438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            lp.cellX, lp.cellY);
13379438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                }
133831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1339cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1340cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final CellLayout parent = (CellLayout) cell.getParent();
1341ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1342ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // Prepare it to be animated into its new position
1343ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // This must be called after the view has been re-parented
1344cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            setPositionForDropAnimation(dragView, originX, originY, parent, cell);
1345cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            parent.onDropChild(cell);
134631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
134731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
134831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1349aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
1350aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
135108ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        mDragTargetLayout = null; // Reset the drag state
135208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
1353d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall) {
135408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            mDragTargetLayout = getCurrentDropLayout();
1355a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            mDragTargetLayout.onDragEnter();
1356d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            showOutlines();
13571b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            mInDragMode = true;
1358d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
135931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
136031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
136118014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka    public DropTarget getDropTargetDelegate(DragSource source, int x, int y,
136218014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
13636569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1364c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1365d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
13660280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return null;
13670280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1368440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
1369440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
1370440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
1371440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
13726569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
1373440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
1374440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1375440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
1376440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
1377440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
1378440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
1379440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
1380440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
1381440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
1382440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
1383440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
1384440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
13850280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointX += mScrollX - currentLayout.getLeft();
13860280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointY += mScrollY - currentLayout.getTop();
1387440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1388440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
1389440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
1390440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
1391440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
1392440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
1393440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
1394440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
1395440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
1396440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
1397440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
1398440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
1399440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
1400440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
14016569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1402a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
1403580e27748137ff08599aa719d106b31215a28353Winson Chung     * Tests to see if the drop will be accepted by Launcher, and if so, includes additional data
1404580e27748137ff08599aa719d106b31215a28353Winson Chung     * in the returned structure related to the widgets that match the drop (or a null list if it is
1405580e27748137ff08599aa719d106b31215a28353Winson Chung     * a shortcut drop).  If the drop is not accepted then a null structure is returned.
1406580e27748137ff08599aa719d106b31215a28353Winson Chung     */
1407580e27748137ff08599aa719d106b31215a28353Winson Chung    private Pair<Integer, List<WidgetMimeTypeHandlerData>> validateDrag(DragEvent event) {
1408580e27748137ff08599aa719d106b31215a28353Winson Chung        final LauncherModel model = mLauncher.getModel();
1409580e27748137ff08599aa719d106b31215a28353Winson Chung        final ClipDescription desc = event.getClipDescription();
1410580e27748137ff08599aa719d106b31215a28353Winson Chung        final int mimeTypeCount = desc.getMimeTypeCount();
1411580e27748137ff08599aa719d106b31215a28353Winson Chung        for (int i = 0; i < mimeTypeCount; ++i) {
1412580e27748137ff08599aa719d106b31215a28353Winson Chung            final String mimeType = desc.getMimeType(i);
1413580e27748137ff08599aa719d106b31215a28353Winson Chung            if (mimeType.equals(InstallShortcutReceiver.SHORTCUT_MIMETYPE)) {
1414580e27748137ff08599aa719d106b31215a28353Winson Chung                return new Pair<Integer, List<WidgetMimeTypeHandlerData>>(i, null);
1415580e27748137ff08599aa719d106b31215a28353Winson Chung            } else {
1416580e27748137ff08599aa719d106b31215a28353Winson Chung                final List<WidgetMimeTypeHandlerData> widgets =
1417580e27748137ff08599aa719d106b31215a28353Winson Chung                    model.resolveWidgetsForMimeType(mContext, mimeType);
1418580e27748137ff08599aa719d106b31215a28353Winson Chung                if (widgets.size() > 0) {
1419580e27748137ff08599aa719d106b31215a28353Winson Chung                    return new Pair<Integer, List<WidgetMimeTypeHandlerData>>(i, widgets);
1420580e27748137ff08599aa719d106b31215a28353Winson Chung                }
1421580e27748137ff08599aa719d106b31215a28353Winson Chung            }
1422580e27748137ff08599aa719d106b31215a28353Winson Chung        }
1423580e27748137ff08599aa719d106b31215a28353Winson Chung        return null;
1424580e27748137ff08599aa719d106b31215a28353Winson Chung    }
1425580e27748137ff08599aa719d106b31215a28353Winson Chung
1426580e27748137ff08599aa719d106b31215a28353Winson Chung    /**
1427a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * Global drag and drop handler
1428a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     */
1429a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    @Override
1430a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    public boolean onDragEvent(DragEvent event) {
143168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung        final ClipDescription desc = event.getClipDescription();
1432a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final CellLayout layout = (CellLayout) getChildAt(mCurrentPage);
1433a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int[] pos = new int[2];
1434a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        layout.getLocationOnScreen(pos);
1435a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        // We need to offset the drag coordinates to layout coordinate space
1436a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int x = (int) event.getX() - pos[0];
1437a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int y = (int) event.getY() - pos[1];
1438a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1439a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        switch (event.getAction()) {
1440580e27748137ff08599aa719d106b31215a28353Winson Chung        case DragEvent.ACTION_DRAG_STARTED: {
1441580e27748137ff08599aa719d106b31215a28353Winson Chung            // Validate this drag
1442580e27748137ff08599aa719d106b31215a28353Winson Chung            Pair<Integer, List<WidgetMimeTypeHandlerData>> test = validateDrag(event);
1443580e27748137ff08599aa719d106b31215a28353Winson Chung            if (test != null) {
1444580e27748137ff08599aa719d106b31215a28353Winson Chung                boolean isShortcut = (test.second == null);
1445580e27748137ff08599aa719d106b31215a28353Winson Chung                if (isShortcut) {
1446580e27748137ff08599aa719d106b31215a28353Winson Chung                    // Check if we have enough space on this screen to add a new shortcut
1447580e27748137ff08599aa719d106b31215a28353Winson Chung                    if (!layout.findCellForSpan(pos, 1, 1)) {
1448580e27748137ff08599aa719d106b31215a28353Winson Chung                        Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
1449580e27748137ff08599aa719d106b31215a28353Winson Chung                                Toast.LENGTH_SHORT).show();
1450580e27748137ff08599aa719d106b31215a28353Winson Chung                        return false;
1451580e27748137ff08599aa719d106b31215a28353Winson Chung                    }
1452580e27748137ff08599aa719d106b31215a28353Winson Chung                }
1453580e27748137ff08599aa719d106b31215a28353Winson Chung            } else {
1454580e27748137ff08599aa719d106b31215a28353Winson Chung                // Show error message if we couldn't accept any of the items
1455580e27748137ff08599aa719d106b31215a28353Winson Chung                Toast.makeText(mContext, mContext.getString(R.string.external_drop_widget_error),
1456a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1457a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return false;
1458a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1459a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
146068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // Create the drag outline
146168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // We need to add extra padding to the bitmap to make room for the glow effect
146268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            final Canvas canvas = new Canvas();
146368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
146468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            mDragOutline = createExternalDragOutline(canvas, bitmapPadding);
1465a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
146668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // Show the current page outlines to indicate that we can accept this drop
146768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            showOutlines();
146868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            layout.setHover(true);
146968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            layout.onDragEnter();
147068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
1471a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
147268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            return true;
1473580e27748137ff08599aa719d106b31215a28353Winson Chung        }
1474a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_LOCATION:
1475a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Visualize the drop location
1476a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
1477a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1478580e27748137ff08599aa719d106b31215a28353Winson Chung        case DragEvent.ACTION_DROP: {
1479a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Try and add any shortcuts
1480a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            int newDropCount = 0;
1481a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final LauncherModel model = mLauncher.getModel();
1482a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final ClipData data = event.getClipData();
148355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung
148468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // We assume that the mime types are ordered in descending importance of
148568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // representation. So we enumerate the list of mime types and alert the
148668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // user if any widgets can handle the drop.  Only the most preferred
148768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // representation will be handled.
148868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            pos[0] = x;
148968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            pos[1] = y;
1490580e27748137ff08599aa719d106b31215a28353Winson Chung            Pair<Integer, List<WidgetMimeTypeHandlerData>> test = validateDrag(event);
1491580e27748137ff08599aa719d106b31215a28353Winson Chung            if (test != null) {
1492580e27748137ff08599aa719d106b31215a28353Winson Chung                final int index = test.first;
1493580e27748137ff08599aa719d106b31215a28353Winson Chung                final List<WidgetMimeTypeHandlerData> widgets = test.second;
1494580e27748137ff08599aa719d106b31215a28353Winson Chung                final boolean isShortcut = (widgets == null);
1495580e27748137ff08599aa719d106b31215a28353Winson Chung                final String mimeType = desc.getMimeType(index);
1496580e27748137ff08599aa719d106b31215a28353Winson Chung                if (isShortcut) {
1497580e27748137ff08599aa719d106b31215a28353Winson Chung                    final Intent intent = data.getItem(index).getIntent();
149868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    Object info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
149968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    onDropExternal(x, y, info, layout);
150068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                } else {
1501580e27748137ff08599aa719d106b31215a28353Winson Chung                    if (widgets.size() == 1) {
150268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        // If there is only one item, then go ahead and add and configure
150368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        // that widget
150468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        final AppWidgetProviderInfo widgetInfo = widgets.get(0).widgetInfo;
150568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        final PendingAddWidgetInfo createInfo =
150668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                                new PendingAddWidgetInfo(widgetInfo, mimeType, data);
150768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        mLauncher.addAppWidgetFromDrop(createInfo, mCurrentPage, pos);
1508580e27748137ff08599aa719d106b31215a28353Winson Chung                    } else {
150968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        // Show the widget picker dialog if there is more than one widget
151068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        // that can handle this data type
151168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        final InstallWidgetReceiver.WidgetListAdapter adapter =
151268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                            new InstallWidgetReceiver.WidgetListAdapter(mLauncher, mimeType,
151368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                                    data, widgets, layout, mCurrentPage, pos);
151468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        final AlertDialog.Builder builder =
151568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                            new AlertDialog.Builder(mContext);
151668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.setAdapter(adapter, adapter);
151768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.setCancelable(true);
151868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.setTitle(mContext.getString(
151968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                                R.string.external_drop_widget_pick_title));
152068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.setIcon(R.drawable.ic_no_applications);
152168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.show();
152255cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    }
1523a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                }
1524a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1525a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1526580e27748137ff08599aa719d106b31215a28353Winson Chung        }
1527a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_ENDED:
1528a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Hide the page outlines after the drop
1529a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.setHover(false);
1530a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.onDragExit();
1531a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            hideOutlines();
1532a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1533a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        }
1534a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        return super.onDragEvent(event);
1535a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
1536a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
15374516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
15384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
15404516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
15414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
15434516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy) {
15444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       mapPointFromSelfToChild(v, xy, null);
15454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
15464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
15484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
15504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
15514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * if cachedInverseMatrix is not null, this method will just use that matrix instead of
1553d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka    * computing it itself; we use this to avoid redundant matrix inversions in
15544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * findMatchingPageForDragOver
15554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
15574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
15584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       if (cachedInverseMatrix == null) {
15594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           v.getMatrix().invert(mTempInverseMatrix);
15604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           cachedInverseMatrix = mTempInverseMatrix;
15614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       }
15624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] = xy[0] + mScrollX - v.getLeft();
15634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] = xy[1] + mScrollY - v.getTop();
15644516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       cachedInverseMatrix.mapPoints(xy);
15654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
15664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15674516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
15684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from this CellLayout's coordinate space to
15704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * the parent View's coordinate space. The argument xy is modified with the return result.
15714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
15734516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromChildToSelf(View v, float[] xy) {
15744516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       v.getMatrix().mapPoints(xy);
15754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] -= (mScrollX - v.getLeft());
15764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] -= (mScrollY - v.getTop());
15774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
15784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    static private float squaredDistance(float[] point1, float[] point2) {
15804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceX = point1[0] - point2[0];
15814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceY = point2[1] - point2[1];
15824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return distanceX * distanceX + distanceY * distanceY;
15830280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
15840280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
15854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
15864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Returns true if the passed CellLayout cl overlaps with dragView
15884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
15904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    boolean overlaps(CellLayout cl, DragView dragView,
15914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
15924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the coordinates of the item being dragged to the CellLayout's coordinates
15934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemTopLeft = mTempDragCoordinates;
15944516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[0] = dragViewX + dragView.getScaledDragRegionXOffset();
15954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[1] = dragViewY + dragView.getScaledDragRegionYOffset();
15964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
15974516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getScaledDragRegionWidth();
15984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getScaledDragRegionHeight();
15994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16004516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the dragged item's top left coordinates
16014516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // to the CellLayout's local coordinates
16024516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
16034516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
16044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
16054516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16064516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
16074516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the dragged item's bottom right coordinates
16084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // to the CellLayout's local coordinates
16094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
16104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
16114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
16124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16134516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
16144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float overlap = (overlapRegionRight - overlapRegionLeft) *
16154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                         (overlapRegionBottom - overlapRegionTop);
16164516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (overlap > 0) {
16174516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    return true;
16184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                }
16194516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka             }
16204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        }
16214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return false;
16224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    }
1623a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
16244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
16254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
16264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * This method returns the CellLayout that is currently being dragged to. In order to drag
16274516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
16284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
16294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
16304516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Return null if no CellLayout is currently being dragged over
16314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
16324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
16334516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private CellLayout findMatchingPageForDragOver(
16344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            DragView dragView, int originX, int originY, int offsetX, int offsetY) {
16354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which ones overlap
16364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // with the item being dragged and then choose the one that's closest to the touch point
1637a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
1638a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
16390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float smallestDistSoFar = Float.MAX_VALUE;
16404516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
1641a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
1642a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
1643a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
16444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            final float[] touchXy = mTempTouchCoordinates;
16454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[0] = originX + offsetX;
16464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[1] = originY + offsetY;
1647a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
16484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the touch coordinates to the CellLayout's local coordinates
16494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // If the touch point is within the bounds of the cell layout, we can return immediately
16500280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cl.getMatrix().invert(mTempInverseMatrix);
16514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
16524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16534516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
16544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
16554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                return cl;
16564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
16574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
16594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Get the center of the cell layout in screen coordinates
16604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
16614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[0] = cl.getWidth()/2;
16624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[1] = cl.getHeight()/2;
16634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                mapPointFromChildToSelf(cl, cellLayoutCenter);
16644516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[0] = originX + offsetX;
16664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[1] = originY + offsetY;
16674516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Calculate the distance between the center of the CellLayout
16694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // and the touch point
16704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float dist = squaredDistance(touchXy, cellLayoutCenter);
16714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (dist < smallestDistSoFar) {
16730280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    smallestDistSoFar = dist;
1674a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
1675a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
16764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
1677a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1678a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
1679a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
1680a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1681440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1682440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
1683d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // When touch is inside the scroll area, skip dragOver actions for the current screen
1684d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mInScrollArea) {
1685d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            CellLayout layout;
1686d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originX = x - xOffset;
1687d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originY = y - yOffset;
1688d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mIsSmall || mIsInUnshrinkAnimation) {
1689d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = findMatchingPageForDragOver(
1690d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        dragView, originX, originY, xOffset, yOffset);
1691d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1692d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1693d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1694d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(false);
1695d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1696d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
1697d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1698d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(true);
1699d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1700d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1701d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            } else {
1702d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = getCurrentDropLayout();
1703d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1704d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                final ItemInfo item = (ItemInfo)dragInfo;
1705d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (dragInfo instanceof LauncherAppWidgetInfo) {
1706d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
1707d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1708d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (widgetInfo.spanX == -1) {
1709d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        // Calculate the grid spans needed to fit this widget
1710d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int[] spans = layout.rectToCell(
1711d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                widgetInfo.minWidth, widgetInfo.minHeight, null);
1712d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanX = spans[0];
1713d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanY = spans[1];
1714d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1715d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1716a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1717d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (source instanceof AllAppsPagedView) {
1718d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // This is a hack to fix the point used to determine which cell an icon from
1719d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // the all apps screen is over
1720d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (item != null && item.spanX == 1 && layout != null) {
1721d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
1722d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1723d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        originX += dragRegionLeft - dragView.getDragRegionLeft();
1724d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
1725d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            dragView.setDragRegion(dragView.getDragRegionLeft(),
1726d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionTop(),
1727d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    layout.getCellWidth(),
1728d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionHeight());
1729d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        }
1730d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1731a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
17321262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1733d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1734d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1735d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.onDragExit();
1736d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1737a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                    layout.onDragEnter();
1738d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
17391262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                }
17406569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1741d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // only visualize the drop locations for moving icons within the home screen on
1742d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // tablet on phone, we also visualize icons dragged in from All Apps
1743d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if ((!LauncherApplication.isScreenXLarge() || source == this)
1744d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        && mDragTargetLayout != null) {
1745d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    final View child = (mDragInfo == null) ? null : mDragInfo.cell;
1746d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
1747d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
1748d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
1749d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            localOriginX, localOriginY, item.spanX, item.spanY);
1750d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
17511262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            }
1752976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
175331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
175431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1755aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
1756aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
17576569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
17580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mDragTargetLayout.onDragExit();
17596569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
17601262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mIsPageMoving) {
17611262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
17621b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            mInDragMode = false;
17631262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
176408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        clearAllHovers();
176531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
176631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1767aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1768aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
176931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
177031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1771aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1772a34abf8c781485b788fddacb352d586bffca886cWinson Chung    @Override
1773a34abf8c781485b788fddacb352d586bffca886cWinson Chung    public void getHitRect(Rect outRect) {
1774a34abf8c781485b788fddacb352d586bffca886cWinson Chung        // We want the workspace to have the whole area of the display (it will find the correct
1775a34abf8c781485b788fddacb352d586bffca886cWinson Chung        // cell layout to drop to in the existing drag/drop logic.
1776a34abf8c781485b788fddacb352d586bffca886cWinson Chung        final Display d = mLauncher.getWindowManager().getDefaultDisplay();
1777a34abf8c781485b788fddacb352d586bffca886cWinson Chung        outRect.set(0, 0, d.getWidth(), d.getHeight());
1778a34abf8c781485b788fddacb352d586bffca886cWinson Chung    }
1779a34abf8c781485b788fddacb352d586bffca886cWinson Chung
17802b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
17812b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
17822b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
17832b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
17842b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
17852b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
17862b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
17872b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
17882b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
17892b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
17900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
179155cef262f97749300c2f6e764da0b00cbcb78879Winson Chung            onDropExternal(-1, -1, dragInfo, cl, false);
17922b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
17932b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
17940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mLauncher.showOutOfSpaceMessage();
17952b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
17962b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
17972b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
17980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    // Drag from somewhere else
17994be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // NOTE: This can also be called when we are outside of a drag event, when we want
18004be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // to add an item to one of the workspace screens.
1801aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1802aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
18030280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int screen = indexOfChild(cellLayout);
18040280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (dragInfo instanceof PendingAddItemInfo) {
18050280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
18060280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // When dragging and dropping from customization tray, we deal with creating
18070280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // widgets/shortcuts/folders in a slightly different way
18080280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            int[] touchXY = new int[2];
18090280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[0] = x;
18100280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[1] = y;
18110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            switch (info.itemType) {
18120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
181355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) info, screen, touchXY);
18140280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
18150280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
18160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
18170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
18180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
18190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
18200280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
18210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                default:
18220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    throw new IllegalStateException("Unknown item type: " + info.itemType);
18230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
18240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
182518014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
18260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return;
18270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
18280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
18290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        // This is for other drag/drop cases, like dragging from All Apps
183031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
183131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1832af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
183331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
183431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
183531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
183631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1837e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
183831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1839aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
184031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1841aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1842aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
184331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
184431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
184531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
1846c9a961952d1a057029874f8426b90181f6876034Michael Jurka                    cellLayout, (UserFolderInfo) info, mIconCache);
1847af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
184831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
18490280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            throw new IllegalStateException("Unknown item type: " + info.itemType);
185031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
185131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18526569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
18536569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
18540280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
18556569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
1856bbc60d8e79416e37cbede55c159bf6aaa6c171d5Winson Chung            mTargetCell = new int[]{x, y};
1857bbc60d8e79416e37cbede55c159bf6aaa6c171d5Winson Chung            cellLayout.findCellForSpan(mTargetCell, 1, 1);
1858aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1859aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1860aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
186118014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
18626569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
186331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1864af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
18650280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1866aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1867af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
186831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1869aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
187070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
187170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
187270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
187370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
187470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
1875d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // if we're currently small, use findMatchingPageForDragOver instead
1876d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mIsSmall) return null;
18770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
187870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
187970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
188031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
188170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
18820280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * Return the current CellInfo describing our current drag; this method exists
18830280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * so that Launcher can sync this object with the correct info when the activity is created/
18840280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * destroyed
18850280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     *
18860280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     */
18870280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public CellLayout.CellInfo getDragInfo() {
18880280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return mDragInfo;
18890280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
18900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
18910280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    /**
189270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
189370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
18946a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka    private int[] findNearestVacantArea(int pixelX, int pixelY,
189570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
18966569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
18975f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
18985f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelY = pixelY - (layout.getTop() - mScrollY);
18996569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
190070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
19010280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return layout.findNearestVacantArea(
1902fc9f07d42511231a26fa182c32e2efaa0f41d478Michael Jurka                localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
190370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1904aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
19058f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
19068f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
19078f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
19088f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
19090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
19108f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
19118f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
191231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
191331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
191431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
191531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
191600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
191700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
191831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
191931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
192031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1921aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
192231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
192331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
192431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
192500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
192600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
192700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1928aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
192931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1930ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
1931cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell);
193231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
193331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19344be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragOutline = null;
193531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
193631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
193731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
19390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return true;
19400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
19410280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
19420142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
19430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
19440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
19450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
19460142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
19470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
19480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
194931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
1950c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
19510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
195231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
195331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
195431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
195631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
1957c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
19580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
195931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
196031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1961138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
19621262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
19631262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onEnterScrollArea(int direction) {
1964d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
1965d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = true;
1966d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            final int screen = getCurrentPage() + ((direction == DragController.SCROLL_LEFT) ? -1 : 1);
1967d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (0 <= screen && screen < getChildCount()) {
1968d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                ((CellLayout) getChildAt(screen)).setHover(true);
19691262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
19700207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                if (mDragTargetLayout != null) {
19710207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    mDragTargetLayout.onDragExit();
19720207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    mDragTargetLayout = null;
19730207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                }
1974d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
19751262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
19761262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
19771262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
197808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    private void clearAllHovers() {
197908ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        final int childCount = getChildCount();
198008ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        for (int i = 0; i < childCount; i++) {
198108ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            ((CellLayout) getChildAt(i)).setHover(false);
198208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        }
198308ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    }
198408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
19851262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
19861262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onExitScrollArea() {
1987d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mInScrollArea) {
1988d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = false;
198908ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            clearAllHovers();
19901262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
19911262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
19921262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
199331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1994dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
199531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
199631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
199731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
199831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
199931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
200031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
200131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
200231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
2003aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
200431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
200531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
200631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
200731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
200831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
200931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
201031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
201131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
201231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
201331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
201431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
201531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
201631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
201731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
201831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
201931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
202031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
202131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
202231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
202331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
202431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
202531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
202631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
202731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
202864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
2029dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
20305c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
2031629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
2032574d20ec84551370987dde530c27ec493bdef564Romain Guy
203364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
203464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
203564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
203664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
203764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
203864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
2039dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
204031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
2041629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
2042629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
2043629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
2044629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
2045629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
2046629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
2047aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2048629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
2049629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
2050629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
2051629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
2052aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
20530589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
20540589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
2055629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
2056629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
2057aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
205864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
205964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
206064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
206164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
206264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
206364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
206464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
2065629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2066629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
2067629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
20680589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
20690589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
2070629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
2071629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
2072aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2073629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
20740589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
2075629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
2076629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
2077aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
207864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
207964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
208064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
208164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
208273013bf94f49ffbacba2b8300f6a2dd4eeebbd13Brad Fitzpatrick                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
208364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
208464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
208564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
2086629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
2087629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2088aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2089629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
2090629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
2091629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
2092aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
2093aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
2094629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2095629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
2096629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
2097629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
2098629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
2099629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
2100629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
2101f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
210264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
210364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
210464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
2105aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
210664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
210764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
2108629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2109629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
2110629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
2111629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
2112629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
2113e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
211464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
211564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
211664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
2117aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
211864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
211964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
2120629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2121574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
2122574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
2123aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2124629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
2125629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
2126629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
2127629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
2128629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
2129629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
2130629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
2131574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
2132aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2133629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
2134629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
2135629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
21365c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
213731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
2138629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
213931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
214031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
2141f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
214264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
2143dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
2144dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
2145f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
2146f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
2147f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
2148f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
2149f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
21500589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
21510589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
2152f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
2153f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
2154f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
2155f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
2156f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
2157f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
215864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
215964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
2160aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
216164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
216264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
216364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
216464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
216564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
216664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
216764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
216864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
2169f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
2170f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
2171f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
2172f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
2173f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
2174f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
217514f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
2176c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
2177c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
2178c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        } else if (animate) {
2179c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            snapToPage(mDefaultPage);
2180c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
21810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
2182c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
21830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
218431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
218531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21868a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
21878a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
21888a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
21890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
21900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
21918a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
21928a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
21930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
21940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
21950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
219631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
21980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
219931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
220131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
2202