Workspace.java revision ded9f8d8658d0b6601006c0a954cd3bf530e55c1
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
230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.Animator;
2468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport android.animation.Animator.AnimatorListener;
2518014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurkaimport android.animation.AnimatorListenerAdapter;
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;
58a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.DragEvent;
5931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
6031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
61cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.view.animation.DecelerateInterpolator;
62f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
63a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.widget.Toast;
6431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport com.android.launcher.R;
6668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chungimport com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
67edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
71aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
730142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
74dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
75e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
763a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
78dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
79dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
80dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
81a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
82f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    // Y rotation to apply to the workspace screens
83f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final float WORKSPACE_ROTATION = 12.5f;
84a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
85a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // These are extra scale factors to apply to the mini home screens
86a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // so as to achieve the desired transform
871b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private static final float EXTRA_SCALE_FACTOR_0 = 0.972f;
88a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
891b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private static final float EXTRA_SCALE_FACTOR_2 = 1.10f;
90a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
91f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DELAY = 300;
92f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DURATION = 300;
93f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_IN_DURATION = 100;
94f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // These animators are used to fade the background
96472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeInAnimation;
97472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeOutAnimation;
98f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private float mBackgroundAlpha = 0;
99f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
1008f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
101aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    private boolean mPageMoving = false;
10521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
110aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
11170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
11270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
11370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
11470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1166569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
1176569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
1186569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
1196569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
1206569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
1220589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
12300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
124aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // These are temporary variables to prevent having to allocate a new object just to
1264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
12870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
1290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private float[] mTempOriginXY = new float[2];
130a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
1314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempTouchCoordinates = new float[2];
1324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempCellLayoutCenterCoordinates = new float[2];
133a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
1340280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private Matrix mTempInverseMatrix = new Matrix();
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
136d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
137d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1398a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1408a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
141aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1421262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    // State variable that indicates whether the pages are small (ie when you're
143dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
144c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsSmall = false;
145c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsInUnshrinkAnimation = false;
146b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
1473e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private enum ShrinkPosition {
1483e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM_HIDDEN, SHRINK_TO_BOTTOM_VISIBLE };
1493e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ShrinkPosition mShrunkenState;
150883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    private boolean mWaitingToShrink = false;
151883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    private ShrinkPosition mWaitingToShrinkPosition;
1523c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka    private AnimatorSet mAnimator;
153dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
1541262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    private boolean mInScrollArea = false;
1551b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private boolean mInDragMode = false;
1561262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1578e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
1584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap mDragOutline = null;
1598e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final Rect mTempRect = new Rect();
1608e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final int[] mTempXY = new int[2];
1614be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
162cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private ValueAnimator mDropAnim = null;
163cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f);
164cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private View mDropView = null;
165cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private int[] mDropViewPos = new int[] { -1, -1 };
166cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
167a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    // Paint used to draw external drop outline
168a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    private final Paint mExternalDragOutlinePaint = new Paint();
169a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1708ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy    /** Used to trigger an animation as soon as the workspace stops scrolling. */
1718ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy    private Animator mAnimOnPageEndMoving = null;
1728ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
17331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
17431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1935f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
1945f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
1955f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFadeInAdjacentScreens = false;
1965f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1988f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
199aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
200aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
201aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
202d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
203d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
2040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
20531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
20631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
207d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
2080d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
2090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
21031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
21131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
21231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
21431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
21531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
2160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
2170589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
2180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
2190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
2200589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
2210589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
222a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        mExternalDragOutlinePaint.setAntiAlias(true);
223cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        setWillNotDraw(false);
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2253c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        mUnshrinkAnimationListener = new LauncherAnimatorListenerAdapter() {
2263c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            @Override
227c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            public void onAnimationStart(Animator animation) {
228c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = true;
229c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            }
2303c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            @Override
2313c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            public void onAnimationEndOrCancel(Animator animation) {
232c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = false;
233dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
234dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
2350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
239f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected int getScrollMode() {
240f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        if (LauncherApplication.isScreenXLarge()) {
241f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.QUINTIC_MODE;
242f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        } else {
243f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.OVERSHOOT_MODE;
244f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
245f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
246f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
247f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
25031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
26121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
27131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
28231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
28821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
29031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
29131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
2990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
300aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
301aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
302aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
303aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
310dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
311dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
313dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
3140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
3150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
3170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
318aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
319aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
320aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
321aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
32631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
32731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
3300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
33131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
3360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
3400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
3410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
34231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
34331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
35031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
359aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
360aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
361aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
362aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
36931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
37031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
37131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
37231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
37331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
37431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
37531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
377291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
378291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
379291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
38031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
38131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
38331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
38931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
39031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
392aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3936569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
394845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
395f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        boolean markCellsAsOccupied = !(child instanceof Folder);
396f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
397aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
398aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
3996569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
400aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
401aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
402aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
40331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
4040d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
40531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
40631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
40700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
408aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
40900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
41031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
41131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
412dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
413dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
414c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4152b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
41696226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
41721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        } else if (!mPageMoving) {
41821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            if (v == getChildAt(mCurrentPage - 1)) {
41921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage - 1);
42021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
42121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            } else if (v == getChildAt(mCurrentPage + 1)) {
42221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage + 1);
42321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
42421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            }
425dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
426dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
4270e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
4280e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
429ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen    protected void onWindowVisibilityChanged (int visibility) {
430ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen        mLauncher.onWindowVisibilityChanged(visibility);
431ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen    }
432ded9f8d8658d0b6601006c0a954cd3bf530e55c1Adam Cohen
4335f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4345f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
435c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4365f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4375f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4385f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4395f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
4405f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4415f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4425f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4435f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
444c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4455f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4465f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4475f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4485f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.onInterceptTouchEvent(ev);
4495f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4505f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4511adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    @Override
4521adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    protected void determineScrollingStart(MotionEvent ev) {
4531adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) super.determineScrollingStart(ev);
4541adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    }
4551adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka
4561262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageBeginMoving() {
4570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
4580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
45916fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage, mNextPage);
4600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
4620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
46316fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
46431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
465f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        showOutlines();
46621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = true;
46731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
46831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4691262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageEndMoving() {
47016fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        clearChildrenCache();
4711262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        // Hide the outlines, as long as we're not dragging
4721262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mDragController.dragging()) {
4731262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
4741262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
4758ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        // Check for an animation that's waiting to be started
4768ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (mAnimOnPageEndMoving != null) {
4778ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving.start();
4788ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving = null;
4798ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
4808ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
48121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = false;
4820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
4830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
4850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
4860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
4870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
4890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
4900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
4910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
4980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
4990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
5000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5018f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
502798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
503798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
504798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
505798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
50686f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
50786f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
50886f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
50986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
51086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
51186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
51286f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
51386f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
51486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
515956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
5168f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
517aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
518f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void showOutlines() {
5193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
5203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
5213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
522472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
523472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
5243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeInAnimation.start();
5253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
526f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
527f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
528f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void hideOutlines() {
5293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
5303e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
5313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
532472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
533472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
5343e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
5353e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.start();
5363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
537f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
538f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
539f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void setBackgroundAlpha(float alpha) {
540f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        mBackgroundAlpha = alpha;
541f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
542f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
543f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            cl.setBackgroundAlpha(alpha);
544f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
545f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
546f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
547f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public float getBackgroundAlpha() {
548f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        return mBackgroundAlpha;
549f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
550f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
551f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
552f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected void screenScrolled(int screenCenter) {
55321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        final int halfScreenSize = getMeasuredWidth() / 2;
55421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
5551b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
5561b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            if (cl != null) {
5571b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                int totalDistance = cl.getMeasuredWidth() + mPageSpacing;
55821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int delta = screenCenter - (getChildOffset(i) -
55921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                        getRelativeChildOffset(i) + halfScreenSize);
560f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
56121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float scrollProgress = delta/(totalDistance*1.0f);
56221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.min(scrollProgress, 1.0f);
56321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.max(scrollProgress, -1.0f);
564f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
5651b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                float mult =  mInDragMode ? 1.0f : Math.abs(scrollProgress);
5661b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                cl.setBackgroundAlphaMultiplier(mult);
5671b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
56821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float rotation = WORKSPACE_ROTATION * scrollProgress;
5691b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                cl.setRotationY(rotation);
570f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            }
571f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
572f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
573f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
57400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
57500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
576956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
57700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
57800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
57900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
58031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
58128750fba6a2d141eb9a1e566718c17236030b815Michael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
5820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
583aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
58479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
58579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
586883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (mWaitingToShrink) {
587883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            shrink(mWaitingToShrinkPosition, false);
588883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrink = false;
58979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
59079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
591aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
592aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
593aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
5940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
595aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
59631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
59731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
600c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
6010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
6020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
6030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
6040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
6050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
6060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
6080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
6090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
6100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
611cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
6120207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            final int width = getWidth();
6130207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            final int height = getHeight();
6140207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
6150207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            // In portrait orientation, draw the glowing edge when dragging to adjacent screens
6160207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            if (mInScrollArea && (height > width)) {
6170207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final int pageHeight = getChildAt(0).getHeight();
6180207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
6190207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                // This determines the height of the glowing edge: 90% of the page height
6200207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final int padding = (int) ((height - pageHeight) * 0.5f + pageHeight * 0.1f);
6210207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
6220207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final CellLayout leftPage = (CellLayout) getChildAt(mCurrentPage - 1);
6230207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                final CellLayout rightPage = (CellLayout) getChildAt(mCurrentPage + 1);
6240207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
6250207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                if (leftPage != null && leftPage.getHover()) {
6260207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    final Drawable d = getResources().getDrawable(R.drawable.page_hover_left);
6270207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    d.setBounds(mScrollX, padding, mScrollX + d.getIntrinsicWidth(), height - padding);
6280207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    d.draw(canvas);
6290207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                } else if (rightPage != null && rightPage.getHover()) {
6300207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    final Drawable d = getResources().getDrawable(R.drawable.page_hover_right);
6310207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    d.setBounds(mScrollX + width - d.getIntrinsicWidth(), padding, mScrollX + width, height - padding);
6320207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    d.draw(canvas);
6330207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                }
6340207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy            }
6350207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy
636cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDropView != null) {
6378ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                // We are animating an item that was just dropped on the home screen.
6388ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                // Render its View in the current animation position.
639cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.save(Canvas.MATRIX_SAVE_FLAG);
640cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final int xPos = mDropViewPos[0] - mDropView.getScrollX();
641cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final int yPos = mDropViewPos[1] - mDropView.getScrollY();
642cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.translate(xPos, yPos);
643cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropView.draw(canvas);
644cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.restore();
645cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
64631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
64731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
64831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
64931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
65031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
651678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
65231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
65331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
65431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
65531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
6560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
65731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
65831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
65931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
66031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
66131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
66231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
663c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
664678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
66531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
6660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
66731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
6680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
6690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
67031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
67131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
67231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
67331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
67431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
6757bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
6767bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
67754dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
67854dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
6796b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
6807bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
6817bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
6827bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
6837bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
6847bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
6857bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
6860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
6870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
6880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
6890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
6900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
6913a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
692aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
693dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
694fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
6960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
697fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
69931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
70031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
70131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
70231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
70331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
70431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
70531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
706dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
707dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
70831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
70931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
71031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
71131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
71231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
71331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
71431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
7152bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
7162bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
7172bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
7182bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
7192bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
7203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            setCurrentPage(mCurrentPage);
7217c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
72231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
72331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7240142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
72531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
726aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
72701f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
72801f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
72901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
73001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
7316b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
7320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
73301f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
73401f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
73501f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
7360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
737213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
738213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
739213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
74079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
74179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
74279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
74379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
744883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, animated);
745213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
746213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
747a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float getYScaleForScreen(int screen) {
748a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int x = Math.abs(screen - 2);
749a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
750a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // TODO: This should be generalized for use with arbitrary rotation angles.
751a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        switch(x) {
752a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 0: return EXTRA_SCALE_FACTOR_0;
753a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 1: return EXTRA_SCALE_FACTOR_1;
754a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 2: return EXTRA_SCALE_FACTOR_2;
755a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
756a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        return 1.0f;
757a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
758a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
759dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
7600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
761883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (mFirstLayout) {
762883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
763883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
764883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
765883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // to get our width so we can layout the mini-screen views correctly
766883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrink = true;
767883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrinkPosition = shrinkPosition;
768883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            return;
769883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        }
770dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
7713e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        mShrunkenState = shrinkPosition;
7723e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7733e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        // Stop any scrolling, move to the current page right away
774a997ac26664befbd0d5b172e36ef9e8b2c63b435Michael Jurka        setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage);
7753e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
7763e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7775f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // we intercept and reject all touch events when we're small, so be sure to reset the state
7785f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mTouchState = TOUCH_STATE_REST;
7795f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mActivePointerId = INVALID_POINTER;
7805f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
7811b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
7821b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        currentPage.setBackgroundAlphaMultiplier(1.0f);
7831b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
7847247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
785dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
786213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
7870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
7890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
7900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
7910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
7930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
794a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
795dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
796dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
797a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
798213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
799df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        boolean isPortrait = getMeasuredHeight() > getMeasuredWidth();
800df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        float newY = (isPortrait ?
801ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginPortrait) :
802ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginLandscape));
8033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float finalAlpha = 1.0f;
8043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float extraShrinkFactor = 1.0f;
8053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
8063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             newY = screenHeight - newY - scaledPageHeight;
8073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
8083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // We shrink and disappear to nothing in the case of all apps
8103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // (which is when we shrink to the bottom)
8110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
8127da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung            finalAlpha = 0.25f;
8130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
814b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            newY = screenHeight / 2 - scaledPageHeight / 2;
815b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            finalAlpha = 1.0f;
816b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_TOP) {
817ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung            newY = (isPortrait ?
818ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginPortrait) :
819ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginLandscape));
820213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
821dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
822dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
823dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
824dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
825dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
8260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
827a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
828a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // We are going to scale about the center of the view, so we need to adjust the positions
829a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // of the views accordingly
830a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newX -= (pageWidth - scaledPageWidth) / 2.0f;
831a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newY -= (pageHeight - scaledPageHeight) / 2.0f;
8323c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka
8333c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        if (mAnimator != null) {
8343c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator.cancel();
8353c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        }
8363c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        mAnimator = new AnimatorSet();
837dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
838dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
839a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
840f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            float rotation = (-i + 2) * WORKSPACE_ROTATION;
841a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
842a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleY = getYScaleForScreen(i);
843a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
84479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
8457247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
846472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(cl,
847472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("x", newX),
848472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("y", newY),
849472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleX",
8503e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleX * extraShrinkFactor),
851472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleY",
8523e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor),
853472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha),
854472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("alpha", finalAlpha),
855472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("rotationY", rotation));
856472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.setDuration(duration);
8573c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.playTogether(anim);
85879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
85979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
86079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
861883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setScaleX(SHRINK_FACTOR * rotationScaleX * extraShrinkFactor);
862883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setScaleY(SHRINK_FACTOR * rotationScaleY * extraShrinkFactor);
863883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setBackgroundAlpha(finalAlpha);
8643e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                cl.setAlpha(finalAlpha);
865a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                cl.setRotationY(rotation);
86679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
867dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
868a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            newX += scaledPageWidth + extraScaledSpacing;
869dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
8703c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        if (animated) {
8713c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator.start();
8723c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        }
873dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
874dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
875dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
8763e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8773e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
8783e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
8793e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8803e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkPosition state, int spanX, int spanY) {
8833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, true, spanX, spanY);
8843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsHelper(
8873e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ShrinkPosition state, boolean isDragHappening, int spanX, int spanY) {
8883e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        final int screenCount = getChildCount();
8893e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        for (int i = 0; i < screenCount; i++) {
8903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
8913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            switch (state) {
8933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_TOP:
8943e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        boolean showDropHighlight = i == mCurrentPage;
8963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        cl.setAcceptsDrops(showDropHighlight);
8973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        break;
8983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8993e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // otherwise, fall through below and mark non-full screens as accepting drops
9003e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_HIDDEN:
9013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_VISIBLE:
9023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
9033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // even if a drag isn't happening, we don't want to show a screen as
9043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // accepting drops if it doesn't have at least one free cell
9053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanX = 1;
9063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanY = 1;
9073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
9083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // the page accepts drops if we can find at least one empty spot
9093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
9103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    break;
9113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                default:
9123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                     throw new RuntimeException(
9133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkPosition");
9143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
9153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
9163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
9183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    /*
9193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
9203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
9213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
9223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
9233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * These methods mark the appropriate pages as accepting drops (which alters their visual
9243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * appearance) and, if the pages are hidden, makes them visible.
9253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
9263e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     */
9273e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemSpans(int spanX, int spanY) {
9283e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsDuringDrag(mShrunkenState, spanX, spanY);
9293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
9303e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE, true);
9313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
9323e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
9343e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemMinSize(int minWidth, int minHeight) {
9353e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        int[] spanXY = CellLayout.rectToCell(getResources(), minWidth, minHeight, null);
9363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        onDragStartedWithItemSpans(spanXY[0], spanXY[1]);
9373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
9393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
9403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // never dragged over
9413e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStopped() {
9423e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
9437da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
9447da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, true);
9457da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung        }
9463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9473e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
948dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
9492b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
9500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
9514cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
9524cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
9534cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
9540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
9554cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
9564cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
9570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
9584cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
9594cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
96021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    @Override
96121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    protected boolean handlePagingClicks() {
96221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        return true;
96321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    }
96421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
9650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
966b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
9675f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
9685f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int delta = newX - mScrollX;
9694cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
970b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
971b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
972b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
973b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
974b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
9750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
976c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            unshrink();
977b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
978dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
979dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
9804cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
9814cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
9824cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
9834cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
9844cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
985b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
986c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mIsSmall = false;
9873c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            if (mAnimator != null) {
9883c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.cancel();
9893c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            }
9903c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator = new AnimatorSet();
991b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
9924cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
9934cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
994b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
9957247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
9965f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
997f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                float rotation = 0.0f;
998f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
999f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (i < mCurrentPage) {
1000f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = WORKSPACE_ROTATION;
1001f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                } else if (i > mCurrentPage) {
1002f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = -WORKSPACE_ROTATION;
1003f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                }
1004f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
10054cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
10063c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                    mAnimator.playTogether(
1007472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationX", 0.0f).setDuration(duration),
1008472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationY", 0.0f).setDuration(duration),
1009472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleX", 1.0f).setDuration(duration),
1010472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleY", 1.0f).setDuration(duration),
1011472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "backgroundAlpha", 0.0f).setDuration(duration),
1012472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "alpha", finalAlphaValue).setDuration(duration),
1013472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "rotationY", rotation).setDuration(duration));
10144cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
10154cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
10164cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
10174cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
10184cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
10195f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setBackgroundAlpha(0.0f);
1020f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setAlpha(finalAlphaValue);
1021f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setRotationY(rotation);
10224cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
1023b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
1024c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            if (animated) {
1025c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // If we call this when we're not animated, onAnimationEnd is never called on
1026c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // the listener; make sure we only use the listener when we're actually animating
10273c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.addListener(mUnshrinkAnimationListener);
10283c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.start();
1029c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            }
1030dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
1031dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
1032dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
10334be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
10344be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Draw the View v into the given Canvas.
10354be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     *
10364be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param v the view to draw
10374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param destCanvas the canvas to draw on
10384be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param padding the horizontal and vertical padding to use when drawing
10394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
10404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private void drawDragView(View v, Canvas destCanvas, int padding) {
10414be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Rect clipRect = mTempRect;
10424be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.getDrawingRect(clipRect);
10434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10444be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // For a TextView, adjust the clip rect so that we don't include the text label
10454be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        if (v instanceof TextView) {
10464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            final int iconHeight = ((TextView)v).getCompoundPaddingTop() - v.getPaddingTop();
10474be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            clipRect.bottom = clipRect.top + iconHeight;
10484be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        }
10494be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10504be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // Draw the View into the bitmap.
10514be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
10524be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // they set scrollX and scrollY to large values to achieve centered text
10534be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10544be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.save();
10554be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
10564be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.clipRect(clipRect, Op.REPLACE);
10574be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.draw(destCanvas);
10584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.restore();
10594be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10604be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10614be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
10624be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
10634be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
10644be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
10654be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {
10664be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
10674be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
10684be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
10694be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10704be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
10714be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
10724be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
10734be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10744be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
10754be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10764be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10774be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
1078a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * Creates a drag outline to represent a drop (that we don't have the actual information for
1079a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * yet).  May be changed in the future to alter the drop outline slightly depending on the
1080a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * clip description mime data.
1081a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     */
1082a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    private Bitmap createExternalDragOutline(Canvas canvas, int padding) {
1083a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        Resources r = getResources();
1084a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int outlineColor = r.getColor(R.color.drag_outline_color);
1085a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int iconWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
1086a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int iconHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height);
1087a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int rectRadius = r.getDimensionPixelSize(R.dimen.external_drop_icon_rect_radius);
1088a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int inset = (int) (Math.min(iconWidth, iconHeight) * 0.2f);
1089a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final Bitmap b = Bitmap.createBitmap(
1090a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                iconWidth + padding, iconHeight + padding, Bitmap.Config.ARGB_8888);
1091a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1092a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        canvas.setBitmap(b);
1093a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        canvas.drawRoundRect(new RectF(inset, inset, iconWidth - inset, iconHeight - inset),
1094a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                rectRadius, rectRadius, mExternalDragOutlinePaint);
1095a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
1096a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1097a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        return b;
1098a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
1099a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1100a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
11014be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to show when the given View is being dragged around.
11024be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
11034be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
11044be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
11054be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
11064be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
11074be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                mDragOutline.getWidth(), mDragOutline.getHeight(), Bitmap.Config.ARGB_8888);
11084be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11094be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
11104be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.drawBitmap(mDragOutline, 0, 0, null);
11114be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
11128e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
11134be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11144be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
11154be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
11164be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
111731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
111831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
1119aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
112031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
11217984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
112231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
112331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
1124aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
112531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
11260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
1127aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
112808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        CellLayout current = getCurrentDropLayout();
112931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
113031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
1131cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        child.setVisibility(View.GONE);
11324be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11334be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.clearFocus();
11344be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.setPressed(false);
11354be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11364be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Canvas canvas = new Canvas();
11374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11388e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        // We need to add extra padding to the bitmap to make room for the glow effect
11398e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
11408e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy
11414be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The outline is used to visualize where the item will land if dropped
11428e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mDragOutline = createDragOutline(child, canvas, bitmapPadding);
11434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11444be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The drag bitmap follows the touch point around on the screen
11458e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final Bitmap b = createDragBitmap(child, canvas, bitmapPadding);
11464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11474be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpWidth = b.getWidth();
11484be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpHeight = b.getHeight();
11494be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.getLocationOnScreen(mTempXY);
11504be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
11514be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
11524be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
11534be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                child.getTag(), DragController.DRAG_ACTION_MOVE, null);
11544be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        b.recycle();
115531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
115631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11570280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
11580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            boolean insertAtFirst, int intersectX, int intersectY) {
11590280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
11600280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
116131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final int[] cellXY = new int[2];
11630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
11640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
11650280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
11660280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
11670280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellXY[0], cellXY[1]);
116831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
116931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1170ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    private void setPositionForDropAnimation(
1171ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            View dragView, int dragViewX, int dragViewY, View parent, View child) {
1172ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
1173ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1174ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // Based on the position of the drag view, find the top left of the original view
1175ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
1176ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
1177ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewX -= getResources().getInteger(R.integer.config_dragViewOffsetX);
1178ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewY -= getResources().getInteger(R.integer.config_dragViewOffsetY);
1179ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1180cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Set its old pos (in the new parent's coordinates); it will be animated
1181cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // in animateViewIntoPosition after the next layout pass
1182ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldX = viewX - (parent.getLeft() - mScrollX);
1183ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldY = viewY - (parent.getTop() - mScrollY);
1184ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    }
11850280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
1186cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    public void animateViewIntoPosition(final View view) {
1187cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final CellLayout parent = (CellLayout) view.getParent();
1188cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
1189cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1190cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Convert the animation params to be relative to the Workspace, not the CellLayout
1191cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int fromX = lp.oldX + parent.getLeft();
1192cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int fromY = lp.oldY + parent.getTop();
1193cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1194cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int dx = lp.x - lp.oldX;
1195cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int dy = lp.y - lp.oldY;
1196cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1197cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Calculate the duration of the animation based on the object's distance
1198cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final float dist = (float) Math.sqrt(dx*dx + dy*dy);
1199cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final Resources res = getResources();
1200cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
12018ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        int duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
12028ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (dist < maxDist) {
12038ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            duration *= mQuintEaseOutInterpolator.getInterpolation(dist / maxDist);
12048ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
1205cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1206f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        if (mDropAnim != null) {
1207f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            // This should really be end(), but that will not be called synchronously,
1208f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            // so instead we use LauncherAnimatorListenerAdapter.onAnimationEndOrCancel()
1209f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            // and call cancel() here.
1210f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            mDropAnim.cancel();
1211f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        }
1212f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        mDropAnim = new ValueAnimator();
1213f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        mDropAnim.setInterpolator(mQuintEaseOutInterpolator);
1214cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1215f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        // The view is invisible during the animation; we render it manually.
1216f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        mDropAnim.addListener(new LauncherAnimatorListenerAdapter() {
1217f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            public void onAnimationStart(Animator animation) {
1218f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                // Set this here so that we don't render it until the animation begins
1219f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                mDropView = view;
1220f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            }
1221f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy
1222f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            public void onAnimationEndOrCancel(Animator animation) {
1223f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                if (mDropView != null) {
1224f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                    mDropView.setVisibility(View.VISIBLE);
1225f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy                    mDropView = null;
1226cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                }
1227f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy            }
1228f24312876b097e25cec922edbb58334ed234dcd7Patrick Dubroy        });
12298ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
1230cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.setDuration(duration);
1231cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.setFloatValues(0.0f, 1.0f);
1232cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.removeAllUpdateListeners();
1233cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.addUpdateListener(new AnimatorUpdateListener() {
1234cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            public void onAnimationUpdate(ValueAnimator animation) {
1235cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final float percent = (Float) animation.getAnimatedValue();
1236cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                // Invalidate the old position
1237cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                invalidate(mDropViewPos[0], mDropViewPos[1],
1238cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
1239cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1240cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropViewPos[0] = fromX + (int) (percent * dx + 0.5f);
1241cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropViewPos[1] = fromY + (int) (percent * dy + 0.5f);
1242cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                invalidate(mDropViewPos[0], mDropViewPos[1],
1243cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
1244cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1245cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        });
12468ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12478ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12488ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        view.setVisibility(View.INVISIBLE);
12498ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12508ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (!mScroller.isFinished()) {
12518ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving = mDropAnim;
12528ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        } else {
12538ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mDropAnim.start();
12548ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
1255cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    }
1256cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1257cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    /**
1258cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy     * {@inheritDoc}
1259cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy     */
1260cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    public boolean acceptDrop(DragSource source, int x, int y,
1261cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
1262cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1263cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // If it's an external drop (e.g. from All Apps), check if it should be accepted
1264cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        if (source != this) {
1265cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            // Don't accept the drop if we're not over a screen at time of drop
1266cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDragTargetLayout == null) {
1267cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                return false;
1268cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1269cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1270cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final CellLayout.CellInfo dragCellInfo = mDragInfo;
1271cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1272cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
1273cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1274cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
1275cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1276cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            // Don't accept the drop if there's no room for the item
1277cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (!mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
1278cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mLauncher.showOutOfSpaceMessage();
1279cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                return false;
1280cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1281cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        }
1282cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        return true;
1283cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    }
1284cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
128500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
128600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
1287ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1288ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originX = x - xOffset;
1289ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originY = y - yOffset;
1290ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1291c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
12920280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
12930280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
12940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
1295d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
12960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
12970280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
1298a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1299c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
130031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
1301d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
1302ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
1303ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            final View cell = mDragInfo.cell;
1304cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDragTargetLayout != null) {
1305cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                // Move internally
1306cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mTargetCell = findNearestVacantArea(originX, originY,
1307cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
1308cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mTargetCell);
1309cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
13109438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                if (mTargetCell == null) {
13118ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                    snapToPage(mDragInfo.screen);
13129438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                } else {
13139438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    int screen = indexOfChild(mDragTargetLayout);
13149438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    if (screen != mDragInfo.screen) {
13159438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        // Reparent the view
13169438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        ((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell);
13179438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
13189438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                                mDragInfo.spanX, mDragInfo.spanY);
13199438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    }
1320cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
13219438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    // update the item's position after drop
13229438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    final ItemInfo info = (ItemInfo) cell.getTag();
13239438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
13249438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
13259438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    lp.cellX = mTargetCell[0];
13269438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    lp.cellY = mTargetCell[1];
13279438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
13289438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
13299438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy
13309438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    LauncherModel.moveItemInDatabase(mLauncher, info,
13319438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
13329438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            lp.cellX, lp.cellY);
13339438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                }
133431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1335cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1336cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final CellLayout parent = (CellLayout) cell.getParent();
1337ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1338ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // Prepare it to be animated into its new position
1339ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // This must be called after the view has been re-parented
1340cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            setPositionForDropAnimation(dragView, originX, originY, parent, cell);
1341cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            parent.onDropChild(cell);
134231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
134331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
134431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1345aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
1346aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
134708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        mDragTargetLayout = null; // Reset the drag state
134808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
1349d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall) {
135008ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            mDragTargetLayout = getCurrentDropLayout();
1351a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            mDragTargetLayout.onDragEnter();
1352d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            showOutlines();
13531b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            mInDragMode = true;
13541b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            CellLayout cl = (CellLayout) getChildAt(mCurrentPage);
13551b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            cl.setBackgroundAlphaMultiplier(1.0f);
1356d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
135731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
135831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
135918014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka    public DropTarget getDropTargetDelegate(DragSource source, int x, int y,
136018014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
13616569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1362c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1363d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
13640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return null;
13650280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1366440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
1367440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
1368440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
1369440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
13706569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
1371440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
1372440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1373440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
1374440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
1375440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
1376440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
1377440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
1378440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
1379440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
1380440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
1381440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
1382440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
13830280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointX += mScrollX - currentLayout.getLeft();
13840280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointY += mScrollY - currentLayout.getTop();
1385440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1386440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
1387440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
1388440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
1389440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
1390440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
1391440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
1392440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
1393440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
1394440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
1395440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
1396440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
1397440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
1398440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
13996569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1400a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
1401a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * Global drag and drop handler
1402a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     */
1403a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    @Override
1404a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    public boolean onDragEvent(DragEvent event) {
140568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung        final ClipDescription desc = event.getClipDescription();
1406a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final CellLayout layout = (CellLayout) getChildAt(mCurrentPage);
1407a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int[] pos = new int[2];
1408a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        layout.getLocationOnScreen(pos);
1409a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        // We need to offset the drag coordinates to layout coordinate space
1410a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int x = (int) event.getX() - pos[0];
1411a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int y = (int) event.getY() - pos[1];
1412a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1413a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        switch (event.getAction()) {
1414a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_STARTED:
1415a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Check if we have enough space on this screen to add a new shortcut
1416a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (!layout.findCellForSpan(pos, 1, 1)) {
1417a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
1418a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1419a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return false;
1420a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1421a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
142268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // Create the drag outline
142368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // We need to add extra padding to the bitmap to make room for the glow effect
142468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            final Canvas canvas = new Canvas();
142568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
142668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            mDragOutline = createExternalDragOutline(canvas, bitmapPadding);
1427a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
142868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // Show the current page outlines to indicate that we can accept this drop
142968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            showOutlines();
143068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            layout.setHover(true);
143168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            layout.onDragEnter();
143268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
1433a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
143468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            return true;
1435a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_LOCATION:
1436a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Visualize the drop location
1437a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
1438a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1439a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DROP:
1440a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Check if we have enough space on this screen to add a new shortcut
1441a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (!layout.findCellForSpan(pos, 1, 1)) {
1442a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
1443a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1444a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return false;
1445a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1446a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1447a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Try and add any shortcuts
1448a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            int newDropCount = 0;
1449a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final LauncherModel model = mLauncher.getModel();
1450a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final ClipData data = event.getClipData();
145155cef262f97749300c2f6e764da0b00cbcb78879Winson Chung
145268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // We assume that the mime types are ordered in descending importance of
145368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // representation. So we enumerate the list of mime types and alert the
145468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // user if any widgets can handle the drop.  Only the most preferred
145568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            // representation will be handled.
145668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            pos[0] = x;
145768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            pos[1] = y;
145868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            final int mimeTypeCount = desc.getMimeTypeCount();
145968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung            for (int j = 0; j < mimeTypeCount; ++j) {
146068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                final String mimeType = desc.getMimeType(j);
146168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung
146268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                if (mimeType.equals(InstallShortcutReceiver.SHORTCUT_MIMETYPE)) {
146368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    final Intent intent = data.getItem(j).getIntent();
146468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    Object info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
146568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    onDropExternal(x, y, info, layout);
146668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                } else {
146768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    final List<WidgetMimeTypeHandlerData> widgets =
146868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        model.resolveWidgetsForMimeType(mContext, mimeType);
146968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    final int numWidgets = widgets.size();
147068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung
147168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    if (numWidgets == 0) {
147268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        continue;
147368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    } else if (numWidgets == 1) {
147468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        // If there is only one item, then go ahead and add and configure
147568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        // that widget
147668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        final AppWidgetProviderInfo widgetInfo = widgets.get(0).widgetInfo;
147768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        final PendingAddWidgetInfo createInfo =
147868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                                new PendingAddWidgetInfo(widgetInfo, mimeType, data);
147968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        mLauncher.addAppWidgetFromDrop(createInfo, mCurrentPage, pos);
148068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                    } else if (numWidgets > 1) {
148168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        // Show the widget picker dialog if there is more than one widget
148268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        // that can handle this data type
148368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        final InstallWidgetReceiver.WidgetListAdapter adapter =
148468846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                            new InstallWidgetReceiver.WidgetListAdapter(mLauncher, mimeType,
148568846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                                    data, widgets, layout, mCurrentPage, pos);
148668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        final AlertDialog.Builder builder =
148768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                            new AlertDialog.Builder(mContext);
148868846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.setAdapter(adapter, adapter);
148968846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.setCancelable(true);
149068846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.setTitle(mContext.getString(
149168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                                R.string.external_drop_widget_pick_title));
149268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.setIcon(R.drawable.ic_no_applications);
149368846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                        builder.show();
149455cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    }
1495a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                }
149668846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                newDropCount++;
149768846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                break;
1498a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1499a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1500a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Show error message if we couldn't accept any of the items
1501a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (newDropCount <= 0) {
150268846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung                Toast.makeText(mContext, mContext.getString(R.string.external_drop_widget_error),
1503a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1504a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1505a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1506a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1507a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_ENDED:
1508a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Hide the page outlines after the drop
1509a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.setHover(false);
1510a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.onDragExit();
1511a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            hideOutlines();
1512a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1513a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        }
1514a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        return super.onDragEvent(event);
1515a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
1516a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
15174516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
15184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15194516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
15204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
15214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
15234516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy) {
15244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       mapPointFromSelfToChild(v, xy, null);
15254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
15264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15274516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
15284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
15304516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
15314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * if cachedInverseMatrix is not null, this method will just use that matrix instead of
1533d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka    * computing it itself; we use this to avoid redundant matrix inversions in
15344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * findMatchingPageForDragOver
15354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
15374516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
15384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       if (cachedInverseMatrix == null) {
15394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           v.getMatrix().invert(mTempInverseMatrix);
15404516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           cachedInverseMatrix = mTempInverseMatrix;
15414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       }
15424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] = xy[0] + mScrollX - v.getLeft();
15434516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] = xy[1] + mScrollY - v.getTop();
15444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       cachedInverseMatrix.mapPoints(xy);
15454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
15464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
15484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from this CellLayout's coordinate space to
15504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * the parent View's coordinate space. The argument xy is modified with the return result.
15514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
15534516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromChildToSelf(View v, float[] xy) {
15544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       v.getMatrix().mapPoints(xy);
15554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] -= (mScrollX - v.getLeft());
15564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] -= (mScrollY - v.getTop());
15574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
15584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    static private float squaredDistance(float[] point1, float[] point2) {
15604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceX = point1[0] - point2[0];
15614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceY = point2[1] - point2[1];
15624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return distanceX * distanceX + distanceY * distanceY;
15630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
15640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
15654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
15664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15674516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Returns true if the passed CellLayout cl overlaps with dragView
15684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
15704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    boolean overlaps(CellLayout cl, DragView dragView,
15714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
15724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the coordinates of the item being dragged to the CellLayout's coordinates
15734516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemTopLeft = mTempDragCoordinates;
15744516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[0] = dragViewX + dragView.getScaledDragRegionXOffset();
15754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[1] = dragViewY + dragView.getScaledDragRegionYOffset();
15764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
15774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getScaledDragRegionWidth();
15784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getScaledDragRegionHeight();
15794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the dragged item's top left coordinates
15814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // to the CellLayout's local coordinates
15824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
15834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
15844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
15854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
15874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the dragged item's bottom right coordinates
15884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // to the CellLayout's local coordinates
15894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
15904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
15914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
15924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
15944516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float overlap = (overlapRegionRight - overlapRegionLeft) *
15954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                         (overlapRegionBottom - overlapRegionTop);
15964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (overlap > 0) {
15974516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    return true;
15984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                }
15994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka             }
16004516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        }
16014516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return false;
16024516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    }
1603a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
16044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
16054516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
16064516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * This method returns the CellLayout that is currently being dragged to. In order to drag
16074516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
16084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
16094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
16104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Return null if no CellLayout is currently being dragged over
16114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
16124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
16134516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private CellLayout findMatchingPageForDragOver(
16144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            DragView dragView, int originX, int originY, int offsetX, int offsetY) {
16154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which ones overlap
16164516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // with the item being dragged and then choose the one that's closest to the touch point
1617a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
1618a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
16190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float smallestDistSoFar = Float.MAX_VALUE;
16204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
1621a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
1622a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
1623a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
16244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            final float[] touchXy = mTempTouchCoordinates;
16254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[0] = originX + offsetX;
16264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[1] = originY + offsetY;
1627a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
16284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the touch coordinates to the CellLayout's local coordinates
16294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // If the touch point is within the bounds of the cell layout, we can return immediately
16300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cl.getMatrix().invert(mTempInverseMatrix);
16314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
16324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16334516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
16344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
16354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                return cl;
16364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
16374516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
16394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Get the center of the cell layout in screen coordinates
16404516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
16414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[0] = cl.getWidth()/2;
16424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[1] = cl.getHeight()/2;
16434516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                mapPointFromChildToSelf(cl, cellLayoutCenter);
16444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[0] = originX + offsetX;
16464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[1] = originY + offsetY;
16474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Calculate the distance between the center of the CellLayout
16494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // and the touch point
16504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float dist = squaredDistance(touchXy, cellLayoutCenter);
16514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (dist < smallestDistSoFar) {
16530280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    smallestDistSoFar = dist;
1654a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
1655a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
16564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
1657a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1658a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
1659a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
1660a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1661440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1662440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
1663d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // When touch is inside the scroll area, skip dragOver actions for the current screen
1664d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mInScrollArea) {
1665d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            CellLayout layout;
1666d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originX = x - xOffset;
1667d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originY = y - yOffset;
1668d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mIsSmall || mIsInUnshrinkAnimation) {
1669d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = findMatchingPageForDragOver(
1670d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        dragView, originX, originY, xOffset, yOffset);
1671d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1672d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1673d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1674d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(false);
1675d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1676d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
1677d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1678d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(true);
1679d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1680d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1681d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            } else {
1682d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = getCurrentDropLayout();
1683d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1684d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                final ItemInfo item = (ItemInfo)dragInfo;
1685d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (dragInfo instanceof LauncherAppWidgetInfo) {
1686d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
1687d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1688d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (widgetInfo.spanX == -1) {
1689d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        // Calculate the grid spans needed to fit this widget
1690d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int[] spans = layout.rectToCell(
1691d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                widgetInfo.minWidth, widgetInfo.minHeight, null);
1692d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanX = spans[0];
1693d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanY = spans[1];
1694d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1695d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1696a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1697d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (source instanceof AllAppsPagedView) {
1698d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // This is a hack to fix the point used to determine which cell an icon from
1699d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // the all apps screen is over
1700d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (item != null && item.spanX == 1 && layout != null) {
1701d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
1702d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1703d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        originX += dragRegionLeft - dragView.getDragRegionLeft();
1704d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
1705d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            dragView.setDragRegion(dragView.getDragRegionLeft(),
1706d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionTop(),
1707d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    layout.getCellWidth(),
1708d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionHeight());
1709d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        }
1710d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1711a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
17121262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1713d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1714d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1715d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.onDragExit();
1716d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1717a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                    layout.onDragEnter();
1718d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
17191262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                }
17206569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1721d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // only visualize the drop locations for moving icons within the home screen on
1722d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // tablet on phone, we also visualize icons dragged in from All Apps
1723d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if ((!LauncherApplication.isScreenXLarge() || source == this)
1724d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        && mDragTargetLayout != null) {
1725d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    final View child = (mDragInfo == null) ? null : mDragInfo.cell;
1726d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
1727d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
1728d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
1729d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            localOriginX, localOriginY, item.spanX, item.spanY);
1730d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
17311262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            }
1732976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
173331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
173431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1735aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
1736aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
17376569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
17380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mDragTargetLayout.onDragExit();
17396569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
17401262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mIsPageMoving) {
17411262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
17421b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            mInDragMode = false;
17431262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
174408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        clearAllHovers();
174531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
174631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1747aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1748aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
174931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
175031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1751aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
17522b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
17532b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
17542b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
17552b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
17562b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
17572b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
17582b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
17592b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
17602b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
17612b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
17620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
176355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung            onDropExternal(-1, -1, dragInfo, cl, false);
17642b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
17652b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
17660280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mLauncher.showOutOfSpaceMessage();
17672b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
17682b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
17692b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
17700280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    // Drag from somewhere else
17714be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // NOTE: This can also be called when we are outside of a drag event, when we want
17724be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // to add an item to one of the workspace screens.
1773aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1774aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
17750280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int screen = indexOfChild(cellLayout);
17760280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (dragInfo instanceof PendingAddItemInfo) {
17770280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
17780280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // When dragging and dropping from customization tray, we deal with creating
17790280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // widgets/shortcuts/folders in a slightly different way
17800280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            int[] touchXY = new int[2];
17810280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[0] = x;
17820280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[1] = y;
17830280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            switch (info.itemType) {
17840280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
178555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) info, screen, touchXY);
17860280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
17870280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
17880280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
17890280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
17900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
17910280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
17920280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
17930280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                default:
17940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    throw new IllegalStateException("Unknown item type: " + info.itemType);
17950280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
17960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
179718014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
17980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return;
17990280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
18000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
18010280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        // This is for other drag/drop cases, like dragging from All Apps
180231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
180331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1804af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
180531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
180631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
180731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
180831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1809e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
181031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1811aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
181231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1813aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1814aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
181531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
181631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
181731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
1818c9a961952d1a057029874f8426b90181f6876034Michael Jurka                    cellLayout, (UserFolderInfo) info, mIconCache);
1819af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
182031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
18210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            throw new IllegalStateException("Unknown item type: " + info.itemType);
182231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
182331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18246569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
18256569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
18260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
18276569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
18287ded67cd64153cd41bb133a6aab11b3254b4a5d9Michael Jurka            mTargetCell = findNearestVacantArea(x, y, 1, 1, null, cellLayout, mTargetCell);
1829aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1830aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1831aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
183218014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
18336569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
183431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1835af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
18360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1837aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1838af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
183931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1840aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
184170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
184270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
184370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
184470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
184570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
1846d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // if we're currently small, use findMatchingPageForDragOver instead
1847d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mIsSmall) return null;
18480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
184970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
185070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
185131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
185270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
18530280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * Return the current CellInfo describing our current drag; this method exists
18540280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * so that Launcher can sync this object with the correct info when the activity is created/
18550280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * destroyed
18560280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     *
18570280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     */
18580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public CellLayout.CellInfo getDragInfo() {
18590280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return mDragInfo;
18600280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
18610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
18620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    /**
186370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
186470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
18656a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka    private int[] findNearestVacantArea(int pixelX, int pixelY,
186670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
18676569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
18685f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
18695f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelY = pixelY - (layout.getTop() - mScrollY);
18706569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
187170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
18720280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return layout.findNearestVacantArea(
1873fc9f07d42511231a26fa182c32e2efaa0f41d478Michael Jurka                localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
187470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1875aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
18768f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
18778f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
18788f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
18798f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
18800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
18818f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
18828f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
188331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
188431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
188531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
188631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
188700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
188800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
188931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
189031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
189131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1892aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
189331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
189431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
189531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
189600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
189700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
189800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1899aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
190031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1901ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
1902cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell);
190331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
190431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19054be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragOutline = null;
190631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
190731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
190831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19090280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
19100280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return true;
19110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
19120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
19130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
19140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
19150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
19160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
19170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
19180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
19190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
192031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
1921c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
19220142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
192331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
192431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
192531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
192731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
1928c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
19290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
193031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
193131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1932138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
19331262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
19341262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onEnterScrollArea(int direction) {
1935d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
1936d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = true;
1937d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            final int screen = getCurrentPage() + ((direction == DragController.SCROLL_LEFT) ? -1 : 1);
1938d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (0 <= screen && screen < getChildCount()) {
1939d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                ((CellLayout) getChildAt(screen)).setHover(true);
19401262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
19410207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                if (mDragTargetLayout != null) {
19420207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    mDragTargetLayout.onDragExit();
19430207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                    mDragTargetLayout = null;
19440207c522472d7252f146f4d39efa456ca5248c6bPatrick Dubroy                }
1945d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
19461262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
19471262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
19481262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
194908ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    private void clearAllHovers() {
195008ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        final int childCount = getChildCount();
195108ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        for (int i = 0; i < childCount; i++) {
195208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            ((CellLayout) getChildAt(i)).setHover(false);
195308ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        }
195408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    }
195508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
19561262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
19571262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onExitScrollArea() {
1958d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mInScrollArea) {
1959d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = false;
196008ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            clearAllHovers();
19611262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
19621262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
19631262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
196431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1965dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
196631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
196731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
196831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
196931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
197031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
197131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
197231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
197331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
1974aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
197531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
197631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
197731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
197831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
197931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
198031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
198131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
198231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
198331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
198431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
198531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
198631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
198731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
198831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
198931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
199031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
199131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
199231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
199331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
199431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
199531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
199631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
199731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
199831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
199964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
2000dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
20015c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
2002629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
2003574d20ec84551370987dde530c27ec493bdef564Romain Guy
200464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
200564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
200664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
200764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
200864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
200964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
2010dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
201131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
2012629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
2013629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
2014629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
2015629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
2016629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
2017629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
2018aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2019629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
2020629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
2021629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
2022629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
2023aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
20240589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
20250589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
2026629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
2027629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
2028aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
202964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
203064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
203164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
203264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
203364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
203464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
203564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
2036629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2037629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
2038629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
20390589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
20400589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
2041629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
2042629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
2043aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2044629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
20450589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
2046629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
2047629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
2048aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
204964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
205064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
205164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
205264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
205373013bf94f49ffbacba2b8300f6a2dd4eeebbd13Brad Fitzpatrick                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
205464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
205564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
205664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
2057629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
2058629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2059aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2060629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
2061629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
2062629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
2063aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
2064aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
2065629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2066629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
2067629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
2068629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
2069629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
2070629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
2071629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
2072f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
207364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
207464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
207564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
2076aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
207764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
207864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
2079629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2080629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
2081629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
2082629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
2083629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
2084e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
208564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
208664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
208764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
2088aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
208964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
209064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
2091629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2092574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
2093574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
2094aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2095629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
2096629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
2097629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
2098629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
2099629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
2100629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
2101629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
2102574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
2103aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2104629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
2105629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
2106629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
21075c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
210831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
2109629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
211031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
211131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
2112f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
211364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
2114dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
2115dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
2116f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
2117f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
2118f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
2119f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
2120f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
21210589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
21220589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
2123f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
2124f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
2125f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
2126f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
2127f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
2128f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
212964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
213064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
2131aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
213264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
213364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
213464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
213564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
213664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
213764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
213864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
213964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
2140f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
2141f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
2142f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
2143f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
2144f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
2145f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
214614f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
2147c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
2148c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
2149c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        } else if (animate) {
2150c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            snapToPage(mDefaultPage);
2151c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
21520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
2153c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
21540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
215531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
215631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21578a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
21588a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
21598a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
21600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
21610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
21628a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
21638a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
21640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
21650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
21660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
216731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
21690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
217031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
21710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
217231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
2173