Workspace.java revision c9a961952d1a057029874f8426b90181f6876034
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
193c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurkaimport com.android.launcher.R;
20495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell
210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.Animator;
2218014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurkaimport android.animation.AnimatorListenerAdapter;
23b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.AnimatorSet;
240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.ObjectAnimator;
250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.PropertyValuesHolder;
26cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.animation.TimeInterpolator;
27cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.animation.ValueAnimator;
283c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurkaimport android.animation.Animator.AnimatorListener;
29cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.animation.ValueAnimator.AnimatorUpdateListener;
308f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.app.WallpaperManager;
31629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetManager;
32629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
33a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.content.ClipData;
34a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.content.ClipDescription;
35495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.ComponentName;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent;
38495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.pm.PackageManager;
395c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.content.pm.ProviderInfo;
407247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.content.res.Resources;
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.TypedArray;
424be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Bitmap;
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
44a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.graphics.Matrix;
45a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.graphics.Paint;
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
47a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.graphics.RectF;
484be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Region.Op;
49f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.graphics.drawable.Drawable;
505c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.net.Uri;
51956091ba7863bd72086275e61084864994dd6fa7Joe Onoratoimport android.os.IBinder;
52495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcelable;
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
54291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandlerimport android.util.Log;
55a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.view.DragEvent;
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
58cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroyimport android.view.animation.DecelerateInterpolator;
59f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
60a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungimport android.widget.Toast;
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
623c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurkaimport java.util.ArrayList;
633c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurkaimport java.util.HashSet;
64edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
68aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
6931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
71dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
72e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
733a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
75dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
76dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
77dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
78a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
79f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    // Y rotation to apply to the workspace screens
80f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final float WORKSPACE_ROTATION = 12.5f;
81a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
82a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // These are extra scale factors to apply to the mini home screens
83a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // so as to achieve the desired transform
841b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private static final float EXTRA_SCALE_FACTOR_0 = 0.972f;
85a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
861b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private static final float EXTRA_SCALE_FACTOR_2 = 1.10f;
87a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
88f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DELAY = 300;
89f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DURATION = 300;
90f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_IN_DURATION = 100;
91f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // These animators are used to fade the background
93472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeInAnimation;
94472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeOutAnimation;
95f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private float mBackgroundAlpha = 0;
96f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
978f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
98aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    private boolean mPageMoving = false;
10221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
107aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
10870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
10970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
11070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
11170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1136569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
1146569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
1156569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
1166569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
1176569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
1190589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
12000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
121aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // These are temporary variables to prevent having to allocate a new object just to
1234516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
12570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
1260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private float[] mTempOriginXY = new float[2];
127a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
1284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempTouchCoordinates = new float[2];
1294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempCellLayoutCenterCoordinates = new float[2];
130a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
1310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private Matrix mTempInverseMatrix = new Matrix();
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
133d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
134d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1368a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1378a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
138aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1391262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    // State variable that indicates whether the pages are small (ie when you're
140dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
141c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsSmall = false;
142c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsInUnshrinkAnimation = false;
143b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
1443e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private enum ShrinkPosition {
1453e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM_HIDDEN, SHRINK_TO_BOTTOM_VISIBLE };
1463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ShrinkPosition mShrunkenState;
147883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    private boolean mWaitingToShrink = false;
148883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka    private ShrinkPosition mWaitingToShrinkPosition;
1493c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka    private AnimatorSet mAnimator;
150dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
1511262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    private boolean mInScrollArea = false;
1521b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen    private boolean mInDragMode = false;
1531262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1548e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
1554be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap mDragOutline = null;
1568e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final Rect mTempRect = new Rect();
1578e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy    private final int[] mTempXY = new int[2];
1584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
159cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private ValueAnimator mDropAnim = null;
160cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f);
161cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private View mDropView = null;
162cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    private int[] mDropViewPos = new int[] { -1, -1 };
163cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
164a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    // Paint used to draw external drop outline
165a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    private final Paint mExternalDragOutlinePaint = new Paint();
166a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1678ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy    /** Used to trigger an animation as soon as the workspace stops scrolling. */
1688ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy    private Animator mAnimOnPageEndMoving = null;
1698ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
17331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
17731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1905f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
1915f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
1925f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFadeInAdjacentScreens = false;
1935f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1958f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
196aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
197aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
198aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
199d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
200d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
2010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
20231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
20331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
204d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
2050d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
2060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
20931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
21131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
21231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
2130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
2140589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
2150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
2160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
2170589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
2180589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
219a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        mExternalDragOutlinePaint.setAntiAlias(true);
220cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        setWillNotDraw(false);
22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2223c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        mUnshrinkAnimationListener = new LauncherAnimatorListenerAdapter() {
2233c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            @Override
224c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            public void onAnimationStart(Animator animation) {
225c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = true;
226c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            }
2273c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            @Override
2283c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            public void onAnimationEndOrCancel(Animator animation) {
229c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = false;
230dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
231dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
2320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
236f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected int getScrollMode() {
237f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        if (LauncherApplication.isScreenXLarge()) {
238f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.QUINTIC_MODE;
239f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        } else {
240f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.OVERSHOOT_MODE;
241f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
242f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
243f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
244f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
25031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
26721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
28231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
28521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
29031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
29131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
29231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
2960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
297aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
298aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
299aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
300aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
30131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
30231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
307dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
308dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
310dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
3110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
3120142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
3140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
315aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
316aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
317aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
318aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
32031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
3270142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
33131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
3330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
3370142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
3380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
34031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
34131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
34231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
34331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
35031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
356aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
357aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
358aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
359aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
36031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
36131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
36931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
37031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
37131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
37231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
37331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
374291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
375291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
376291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
37831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
37931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
38031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
38131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
38231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
38331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
389aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3906569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
391845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
392f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        boolean markCellsAsOccupied = !(child instanceof Folder);
393f3ca3ab6958b104cbf2c2fa04add97d372a94d1cMichael Jurka        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
394aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
395aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
3966569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
397aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
398aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
399aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
40031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
4010d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
40231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
40331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
40400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
405aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
40600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
40731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
40831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
409dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
410dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
411c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4122b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
41396226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
41421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        } else if (!mPageMoving) {
41521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            if (v == getChildAt(mCurrentPage - 1)) {
41621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage - 1);
41721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
41821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            } else if (v == getChildAt(mCurrentPage + 1)) {
41921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage + 1);
42021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
42121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            }
422dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
423dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
4240e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
4250e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
4265f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4275f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
428c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4295f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4305f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4315f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4325f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
4335f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4345f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4355f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4365f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
437c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4385f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4395f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4405f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4415f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.onInterceptTouchEvent(ev);
4425f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4435f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4441adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    @Override
4451adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    protected void determineScrollingStart(MotionEvent ev) {
4461adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) super.determineScrollingStart(ev);
4471adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka    }
4481adf5391a3a3d215b226adf3702019c22a99e3b1Michael Jurka
4491262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageBeginMoving() {
4500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
4510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
45216fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage, mNextPage);
4530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
4550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
45616fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
45731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
458f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        showOutlines();
45921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = true;
46031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
46131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4621262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageEndMoving() {
46316fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        clearChildrenCache();
4641262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        // Hide the outlines, as long as we're not dragging
4651262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mDragController.dragging()) {
4661262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
4671262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
4688ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        // Check for an animation that's waiting to be started
4698ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (mAnimOnPageEndMoving != null) {
4708ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving.start();
4718ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving = null;
4728ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
4738ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
47421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = false;
4750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
4760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
4780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
4790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
4800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
4820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
4830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
4840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
4910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
4920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
4930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4948f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
495798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
496798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
497798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
498798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
49986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
50086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
50186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
50286f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
50386f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
50486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
50586f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
50686f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
50786f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
508956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
5098f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
510aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
511f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void showOutlines() {
5123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
5133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
5143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
515472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
516472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
5173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeInAnimation.start();
5183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
519f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
520f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
521f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void hideOutlines() {
5223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
5233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
5243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
525472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
526472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
5273e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
5283e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.start();
5293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
530f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
531f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
532f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void setBackgroundAlpha(float alpha) {
533f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        mBackgroundAlpha = alpha;
534f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
535f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
536f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            cl.setBackgroundAlpha(alpha);
537f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
538f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
539f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
540f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public float getBackgroundAlpha() {
541f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        return mBackgroundAlpha;
542f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
543f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
544f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
545f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected void screenScrolled(int screenCenter) {
54621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        final int halfScreenSize = getMeasuredWidth() / 2;
54721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
5481b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
5491b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            if (cl != null) {
5501b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                int totalDistance = cl.getMeasuredWidth() + mPageSpacing;
55121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int delta = screenCenter - (getChildOffset(i) -
55221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                        getRelativeChildOffset(i) + halfScreenSize);
553f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
55421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float scrollProgress = delta/(totalDistance*1.0f);
55521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.min(scrollProgress, 1.0f);
55621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.max(scrollProgress, -1.0f);
557f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
5581b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                float mult =  mInDragMode ? 1.0f : Math.abs(scrollProgress);
5591b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                cl.setBackgroundAlphaMultiplier(mult);
5601b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
56121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float rotation = WORKSPACE_ROTATION * scrollProgress;
5621b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen                cl.setRotationY(rotation);
563f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            }
564f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
565f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
566f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
56700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
56800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
569956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
57000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
57100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
57200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
57331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
57428750fba6a2d141eb9a1e566718c17236030b815Michael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
5750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
576aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
57779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
57879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
579883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (mWaitingToShrink) {
580883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            shrink(mWaitingToShrinkPosition, false);
581883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrink = false;
58279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
58379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
584aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
585aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
586aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
5870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
588aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
58931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
59031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
593c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
5940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
5950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
5960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
5970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
5980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
5990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
6010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
6020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
6030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
604cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
605cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDropView != null) {
6068ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                // We are animating an item that was just dropped on the home screen.
6078ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                // Render its View in the current animation position.
608cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.save(Canvas.MATRIX_SAVE_FLAG);
609cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final int xPos = mDropViewPos[0] - mDropView.getScrollX();
610cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final int yPos = mDropViewPos[1] - mDropView.getScrollY();
611cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.translate(xPos, yPos);
612cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropView.draw(canvas);
613cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                canvas.restore();
614cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
61531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
61631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
61731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
61831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
61931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
620678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
62131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
62231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
62331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
62431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
6250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
62631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
62731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
62831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
62931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
63031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
63131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
632c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
633678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
63431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
6350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
63631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
6370142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
6380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
63931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
64031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
64131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
64231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
64331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
6447bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
6457bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
64654dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
64754dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
6486b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
6497bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
6507bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
6517bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
6527bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
6537bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
6547bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
6550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
6560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
6570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
6580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
6590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
6603a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
661aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
662dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
663fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
6650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
666fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
66831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
66931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
67031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
67131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
67231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
67331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
67431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
675dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
676dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
67731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
67831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
67931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
68031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
68131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
68231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
68331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
6842bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
6852bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
6862bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
6872bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
6882bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
6893e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            setCurrentPage(mCurrentPage);
6907c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
69131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
69231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
69431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
695aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
69601f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
69701f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
69801f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
69901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
7006b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
7010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
70201f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
70301f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
70401f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
7050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
706213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
707213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
708213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
70979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
71079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
71179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
71279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
713883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, animated);
714213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
715213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
716a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float getYScaleForScreen(int screen) {
717a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int x = Math.abs(screen - 2);
718a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
719a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // TODO: This should be generalized for use with arbitrary rotation angles.
720a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        switch(x) {
721a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 0: return EXTRA_SCALE_FACTOR_0;
722a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 1: return EXTRA_SCALE_FACTOR_1;
723a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 2: return EXTRA_SCALE_FACTOR_2;
724a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
725a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        return 1.0f;
726a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
727a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
728dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
7290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
730883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        if (mFirstLayout) {
731883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
732883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
733883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
734883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            // to get our width so we can layout the mini-screen views correctly
735883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrink = true;
736883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            mWaitingToShrinkPosition = shrinkPosition;
737883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka            return;
738883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka        }
739dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
7403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        mShrunkenState = shrinkPosition;
7413e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7423e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        // Stop any scrolling, move to the current page right away
743a997ac26664befbd0d5b172e36ef9e8b2c63b435Michael Jurka        setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage);
7443e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
7453e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7465f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // we intercept and reject all touch events when we're small, so be sure to reset the state
7475f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mTouchState = TOUCH_STATE_REST;
7485f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mActivePointerId = INVALID_POINTER;
7495f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
7501b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
7511b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen        currentPage.setBackgroundAlphaMultiplier(1.0f);
7521b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen
7537247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
754dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
755213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
7560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
7580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
7590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
7600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
7620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
763a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
764dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
765dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
766a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
767213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
768df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        boolean isPortrait = getMeasuredHeight() > getMeasuredWidth();
769df4b83dd9d6380ab963c62d1f9d1312efc87cb0fWinson Chung        float newY = (isPortrait ?
770ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginPortrait) :
771ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginLandscape));
7723e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float finalAlpha = 1.0f;
7733e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float extraShrinkFactor = 1.0f;
7743e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
7753e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             newY = screenHeight - newY - scaledPageHeight;
7763e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
7773e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7783e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // We shrink and disappear to nothing in the case of all apps
7793e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // (which is when we shrink to the bottom)
7800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
7817da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung            finalAlpha = 0.25f;
7820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
783b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            newY = screenHeight / 2 - scaledPageHeight / 2;
784b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            finalAlpha = 1.0f;
785b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_TOP) {
786ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung            newY = (isPortrait ?
787ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginPortrait) :
788ef0066b52d2754ca0553ec79613c650b5649afaaWinson Chung                getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginLandscape));
789213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
790dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
791dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
792dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
793dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
794dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
7950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
796a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
797a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // We are going to scale about the center of the view, so we need to adjust the positions
798a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // of the views accordingly
799a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newX -= (pageWidth - scaledPageWidth) / 2.0f;
800a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newY -= (pageHeight - scaledPageHeight) / 2.0f;
8013c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka
8023c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        if (mAnimator != null) {
8033c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator.cancel();
8043c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        }
8053c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        mAnimator = new AnimatorSet();
806dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
807dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
808a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
809f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            float rotation = (-i + 2) * WORKSPACE_ROTATION;
810a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
811a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleY = getYScaleForScreen(i);
812a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
81379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
8147247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
815472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(cl,
816472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("x", newX),
817472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("y", newY),
818472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleX",
8193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleX * extraShrinkFactor),
820472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleY",
8213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor),
822472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha),
823472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("alpha", finalAlpha),
824472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("rotationY", rotation));
825472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.setDuration(duration);
8263c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.playTogether(anim);
82779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
82879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
82979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
830883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setScaleX(SHRINK_FACTOR * rotationScaleX * extraShrinkFactor);
831883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setScaleY(SHRINK_FACTOR * rotationScaleY * extraShrinkFactor);
832883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka                cl.setBackgroundAlpha(finalAlpha);
8333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                cl.setAlpha(finalAlpha);
834a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                cl.setRotationY(rotation);
83579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
836dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
837a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            newX += scaledPageWidth + extraScaledSpacing;
838dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
8393c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        if (animated) {
8403c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator.start();
8413c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka        }
842dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
843dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
844dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
8453e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
8473e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
8483e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8493e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8503e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8513e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkPosition state, int spanX, int spanY) {
8523e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, true, spanX, spanY);
8533e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8543e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8553e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsHelper(
8563e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ShrinkPosition state, boolean isDragHappening, int spanX, int spanY) {
8573e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        final int screenCount = getChildCount();
8583e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        for (int i = 0; i < screenCount; i++) {
8593e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
8603e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8613e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            switch (state) {
8623e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_TOP:
8633e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8643e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        boolean showDropHighlight = i == mCurrentPage;
8653e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        cl.setAcceptsDrops(showDropHighlight);
8663e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        break;
8673e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8683e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // otherwise, fall through below and mark non-full screens as accepting drops
8693e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_HIDDEN:
8703e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_VISIBLE:
8713e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8723e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // even if a drag isn't happening, we don't want to show a screen as
8733e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // accepting drops if it doesn't have at least one free cell
8743e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanX = 1;
8753e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanY = 1;
8763e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8773e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // the page accepts drops if we can find at least one empty spot
8783e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
8793e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    break;
8803e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                default:
8813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                     throw new RuntimeException(
8823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkPosition");
8833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
8843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8873e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    /*
8883e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8893e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
8903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
8913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * These methods mark the appropriate pages as accepting drops (which alters their visual
8933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * appearance) and, if the pages are hidden, makes them visible.
8943e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     */
8963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemSpans(int spanX, int spanY) {
8973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsDuringDrag(mShrunkenState, spanX, spanY);
8983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
8993e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE, true);
9003e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
9013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
9033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemMinSize(int minWidth, int minHeight) {
9043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        int[] spanXY = CellLayout.rectToCell(getResources(), minWidth, minHeight, null);
9053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        onDragStartedWithItemSpans(spanXY[0], spanXY[1]);
9063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
9083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
9093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // never dragged over
9103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStopped() {
9113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
9127da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
9137da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, true);
9147da1025bd7f15b04cf55c79b73e94e5e1bc959d9Winson Chung        }
9153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
9163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
917dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
9182b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
9190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
9204cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
9214cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
9224cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
9230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
9244cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
9254cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
9260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
9274cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
9284cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
92921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    @Override
93021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    protected boolean handlePagingClicks() {
93121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        return true;
93221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    }
93321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
9340142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
935b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
9365f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
9375f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int delta = newX - mScrollX;
9384cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
939b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
940b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
941b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
942b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
943b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
9440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
945c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            unshrink();
946b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
947dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
948dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
9494cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
9504cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
9514cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
9524cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
9534cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
954b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
955c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mIsSmall = false;
9563c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            if (mAnimator != null) {
9573c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.cancel();
9583c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            }
9593c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka            mAnimator = new AnimatorSet();
960b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
9614cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
9624cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
963b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
9647247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
9655f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
966f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                float rotation = 0.0f;
967f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
968f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (i < mCurrentPage) {
969f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = WORKSPACE_ROTATION;
970f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                } else if (i > mCurrentPage) {
971f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = -WORKSPACE_ROTATION;
972f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                }
973f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
9744cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
9753c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                    mAnimator.playTogether(
976472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationX", 0.0f).setDuration(duration),
977472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationY", 0.0f).setDuration(duration),
978472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleX", 1.0f).setDuration(duration),
979472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleY", 1.0f).setDuration(duration),
980472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "backgroundAlpha", 0.0f).setDuration(duration),
981472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "alpha", finalAlphaValue).setDuration(duration),
982472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "rotationY", rotation).setDuration(duration));
9834cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
9844cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
9854cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
9864cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
9874cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
9885f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setBackgroundAlpha(0.0f);
989f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setAlpha(finalAlphaValue);
990f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setRotationY(rotation);
9914cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
992b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
993c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            if (animated) {
994c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // If we call this when we're not animated, onAnimationEnd is never called on
995c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // the listener; make sure we only use the listener when we're actually animating
9963c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.addListener(mUnshrinkAnimationListener);
9973c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka                mAnimator.start();
998c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            }
999dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
1000dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
1001dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
10024be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
10034be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Draw the View v into the given Canvas.
10044be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     *
10054be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param v the view to draw
10064be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param destCanvas the canvas to draw on
10074be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param padding the horizontal and vertical padding to use when drawing
10084be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
10094be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private void drawDragView(View v, Canvas destCanvas, int padding) {
10104be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Rect clipRect = mTempRect;
10114be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.getDrawingRect(clipRect);
10124be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10134be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // For a TextView, adjust the clip rect so that we don't include the text label
10144be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        if (v instanceof TextView) {
10154be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            final int iconHeight = ((TextView)v).getCompoundPaddingTop() - v.getPaddingTop();
10164be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            clipRect.bottom = clipRect.top + iconHeight;
10174be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        }
10184be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10194be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // Draw the View into the bitmap.
10204be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
10214be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // they set scrollX and scrollY to large values to achieve centered text
10224be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10234be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.save();
10244be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
10254be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.clipRect(clipRect, Op.REPLACE);
10264be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.draw(destCanvas);
10274be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.restore();
10284be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10294be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10304be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
10314be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
10324be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
10334be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
10344be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {
10354be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
10364be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
10374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
10384be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
10404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
10414be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
10424be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
10444be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10454be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
1047a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * Creates a drag outline to represent a drop (that we don't have the actual information for
1048a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * yet).  May be changed in the future to alter the drop outline slightly depending on the
1049a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * clip description mime data.
1050a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     */
1051a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    private Bitmap createExternalDragOutline(Canvas canvas, int padding) {
1052a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        Resources r = getResources();
1053a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int outlineColor = r.getColor(R.color.drag_outline_color);
1054a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int iconWidth = r.getDimensionPixelSize(R.dimen.workspace_cell_width);
1055a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int iconHeight = r.getDimensionPixelSize(R.dimen.workspace_cell_height);
1056a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int rectRadius = r.getDimensionPixelSize(R.dimen.external_drop_icon_rect_radius);
1057a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int inset = (int) (Math.min(iconWidth, iconHeight) * 0.2f);
1058a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final Bitmap b = Bitmap.createBitmap(
1059a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                iconWidth + padding, iconHeight + padding, Bitmap.Config.ARGB_8888);
1060a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1061a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        canvas.setBitmap(b);
1062a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        canvas.drawRoundRect(new RectF(inset, inset, iconWidth - inset, iconHeight - inset),
1063a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                rectRadius, rectRadius, mExternalDragOutlinePaint);
1064a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
1065a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1066a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        return b;
1067a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
1068a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1069a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
10704be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to show when the given View is being dragged around.
10714be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
10724be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
10734be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
10744be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
10754be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
10764be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                mDragOutline.getWidth(), mDragOutline.getHeight(), Bitmap.Config.ARGB_8888);
10774be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10784be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
10794be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.drawBitmap(mDragOutline, 0, 0, null);
10804be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
10818e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
10824be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10834be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
10844be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
10854be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
108631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
108731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
1088aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
108931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
10907984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
109131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
109231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
1093aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
109431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
10950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
1096aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
109708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        CellLayout current = getCurrentDropLayout();
109831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
109931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
1100cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        child.setVisibility(View.GONE);
11014be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11024be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.clearFocus();
11034be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.setPressed(false);
11044be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11054be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Canvas canvas = new Canvas();
11064be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11078e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        // We need to add extra padding to the bitmap to make room for the glow effect
11088e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
11098e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy
11104be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The outline is used to visualize where the item will land if dropped
11118e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        mDragOutline = createDragOutline(child, canvas, bitmapPadding);
11124be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11134be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The drag bitmap follows the touch point around on the screen
11148e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy        final Bitmap b = createDragBitmap(child, canvas, bitmapPadding);
11154be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
11164be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpWidth = b.getWidth();
11174be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpHeight = b.getHeight();
11184be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.getLocationOnScreen(mTempXY);
11194be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
11204be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
11214be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
11224be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                child.getTag(), DragController.DRAG_ACTION_MOVE, null);
11234be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        b.recycle();
112431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
112531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
11270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            boolean insertAtFirst, int intersectX, int intersectY) {
11280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
11290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
113031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final int[] cellXY = new int[2];
11320280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
11330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
11340280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
11350280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
11360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellXY[0], cellXY[1]);
113731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
113831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1139ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    private void setPositionForDropAnimation(
1140ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            View dragView, int dragViewX, int dragViewY, View parent, View child) {
1141ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
1142ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1143ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        // Based on the position of the drag view, find the top left of the original view
1144ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewX = dragViewX + (dragView.getWidth() - child.getWidth()) / 2;
1145ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int viewY = dragViewY + (dragView.getHeight() - child.getHeight()) / 2;
1146ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewX -= getResources().getInteger(R.integer.config_dragViewOffsetX);
1147ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        viewY -= getResources().getInteger(R.integer.config_dragViewOffsetY);
1148ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1149cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Set its old pos (in the new parent's coordinates); it will be animated
1150cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // in animateViewIntoPosition after the next layout pass
1151ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldX = viewX - (parent.getLeft() - mScrollX);
1152ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        lp.oldY = viewY - (parent.getTop() - mScrollY);
1153ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy    }
11540280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
1155cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    public void animateViewIntoPosition(final View view) {
1156cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final CellLayout parent = (CellLayout) view.getParent();
1157cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
1158cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1159cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Convert the animation params to be relative to the Workspace, not the CellLayout
1160cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int fromX = lp.oldX + parent.getLeft();
1161cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int fromY = lp.oldY + parent.getTop();
1162cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1163cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int dx = lp.x - lp.oldX;
1164cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final int dy = lp.y - lp.oldY;
1165cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1166cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Calculate the duration of the animation based on the object's distance
1167cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final float dist = (float) Math.sqrt(dx*dx + dy*dy);
1168cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final Resources res = getResources();
1169cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
11708ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        int duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
11718ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (dist < maxDist) {
11728ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            duration *= mQuintEaseOutInterpolator.getInterpolation(dist / maxDist);
11738ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
1174cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1175cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // Lazy initialize the animation
1176cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        if (mDropAnim == null) {
1177cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            mDropAnim = new ValueAnimator();
1178cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            mDropAnim.setInterpolator(mQuintEaseOutInterpolator);
1179cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
11808ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            // The view is invisible during the animation; we render it manually.
1181cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            mDropAnim.addListener(new AnimatorListenerAdapter() {
1182cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                public void onAnimationStart(Animator animation) {
11838ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                    // Set this here so that we don't render it until the animation begins
11848ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                    mDropView = view;
1185cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                }
1186cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1187cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                public void onAnimationEnd(Animator animation) {
1188cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                    if (mDropView != null) {
1189cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDropView.setVisibility(View.VISIBLE);
1190cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDropView = null;
1191cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                    }
1192cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                }
1193cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            });
1194cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        } else {
1195cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            mDropAnim.end(); // Make sure it's not already running
1196cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        }
11978ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
1198cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.setDuration(duration);
1199cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.setFloatValues(0.0f, 1.0f);
1200cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.removeAllUpdateListeners();
1201cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        mDropAnim.addUpdateListener(new AnimatorUpdateListener() {
1202cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            public void onAnimationUpdate(ValueAnimator animation) {
1203cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                final float percent = (Float) animation.getAnimatedValue();
1204cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                // Invalidate the old position
1205cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                invalidate(mDropViewPos[0], mDropViewPos[1],
1206cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
1207cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1208cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropViewPos[0] = fromX + (int) (percent * dx + 0.5f);
1209cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mDropViewPos[1] = fromY + (int) (percent * dy + 0.5f);
1210cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                invalidate(mDropViewPos[0], mDropViewPos[1],
1211cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
1212cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1213cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        });
12148ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12158ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12168ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        view.setVisibility(View.INVISIBLE);
12178ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy
12188ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        if (!mScroller.isFinished()) {
12198ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mAnimOnPageEndMoving = mDropAnim;
12208ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        } else {
12218ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy            mDropAnim.start();
12228ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy        }
1223cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    }
1224cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1225cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    /**
1226cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy     * {@inheritDoc}
1227cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy     */
1228cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    public boolean acceptDrop(DragSource source, int x, int y,
1229cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
1230cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1231cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        // If it's an external drop (e.g. from All Apps), check if it should be accepted
1232cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        if (source != this) {
1233cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            // Don't accept the drop if we're not over a screen at time of drop
1234cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDragTargetLayout == null) {
1235cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                return false;
1236cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1237cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1238cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final CellLayout.CellInfo dragCellInfo = mDragInfo;
1239cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1240cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
1241cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1242cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
1243cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1244cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            // Don't accept the drop if there's no room for the item
1245cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (!mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
1246cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mLauncher.showOutOfSpaceMessage();
1247cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                return false;
1248cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            }
1249cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        }
1250cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy        return true;
1251cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    }
1252cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
125300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
125400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
1255ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1256ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originX = x - xOffset;
1257ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        int originY = y - yOffset;
1258ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1259c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
12600280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
12610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
12620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
1263d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
12640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
12650280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
1266a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1267c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
126831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
1269d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
1270ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
1271ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            final View cell = mDragInfo.cell;
1272cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            if (mDragTargetLayout != null) {
1273cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                // Move internally
1274cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                mTargetCell = findNearestVacantArea(originX, originY,
1275cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
1276cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy                        mTargetCell);
1277cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
12789438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                if (mTargetCell == null) {
12798ae3a62e2e48dfb8f860c8b6e2c7e72b9595d7aaPatrick Dubroy                    snapToPage(mDragInfo.screen);
12809438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                } else {
12819438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    int screen = indexOfChild(mDragTargetLayout);
12829438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    if (screen != mDragInfo.screen) {
12839438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        // Reparent the view
12849438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        ((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell);
12859438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                        addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
12869438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                                mDragInfo.spanX, mDragInfo.spanY);
12879438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    }
1288cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
12899438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    // update the item's position after drop
12909438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    final ItemInfo info = (ItemInfo) cell.getTag();
12919438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
12929438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
12939438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    lp.cellX = mTargetCell[0];
12949438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    lp.cellY = mTargetCell[1];
12959438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
12969438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
12979438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy
12989438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                    LauncherModel.moveItemInDatabase(mLauncher, info,
12999438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
13009438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                            lp.cellX, lp.cellY);
13019438336724b4f8b54c7cdc49c5f01dd9568926ebPatrick Dubroy                }
130231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1303cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
1304cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            final CellLayout parent = (CellLayout) cell.getParent();
1305ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy
1306ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // Prepare it to be animated into its new position
1307ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy            // This must be called after the view has been re-parented
1308cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            setPositionForDropAnimation(dragView, originX, originY, parent, cell);
1309cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            parent.onDropChild(cell);
131031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
131131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
131231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1313aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
1314aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
131508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        mDragTargetLayout = null; // Reset the drag state
131608ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
1317d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall) {
131808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            mDragTargetLayout = getCurrentDropLayout();
1319a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            mDragTargetLayout.onDragEnter();
1320d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            showOutlines();
13211b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            mInDragMode = true;
13221b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            CellLayout cl = (CellLayout) getChildAt(mCurrentPage);
13231b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            cl.setBackgroundAlphaMultiplier(1.0f);
1324d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
132531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
132631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
132718014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka    public DropTarget getDropTargetDelegate(DragSource source, int x, int y,
132818014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
13296569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1330c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1331d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
13320280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return null;
13330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1334440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
1335440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
1336440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
1337440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
13386569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
1339440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
1340440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1341440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
1342440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
1343440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
1344440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
1345440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
1346440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
1347440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
1348440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
1349440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
1350440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
13510280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointX += mScrollX - currentLayout.getLeft();
13520280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointY += mScrollY - currentLayout.getTop();
1353440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1354440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
1355440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
1356440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
1357440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
1358440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
1359440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
1360440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
1361440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
1362440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
1363440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
1364440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
1365440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
1366440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
13676569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1368a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    /**
1369a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     * Global drag and drop handler
1370a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung     */
1371a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    @Override
1372a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    public boolean onDragEvent(DragEvent event) {
1373a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final CellLayout layout = (CellLayout) getChildAt(mCurrentPage);
1374a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int[] pos = new int[2];
1375a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        layout.getLocationOnScreen(pos);
1376a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        // We need to offset the drag coordinates to layout coordinate space
1377a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int x = (int) event.getX() - pos[0];
1378a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        final int y = (int) event.getY() - pos[1];
1379a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1380a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        switch (event.getAction()) {
1381a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_STARTED:
1382a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Check if we have enough space on this screen to add a new shortcut
1383a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (!layout.findCellForSpan(pos, 1, 1)) {
1384a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
1385a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1386a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return false;
1387a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1388a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1389a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            ClipDescription desc = event.getClipDescription();
1390a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (desc.filterMimeTypes(ClipDescription.MIMETYPE_TEXT_INTENT) != null) {
1391a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                // Create the drag outline
1392a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                // We need to add extra padding to the bitmap to make room for the glow effect
1393a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                final Canvas canvas = new Canvas();
1394a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                final int bitmapPadding = HolographicOutlineHelper.OUTER_BLUR_RADIUS;
1395a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                mDragOutline = createExternalDragOutline(canvas, bitmapPadding);
1396a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1397a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                // Show the current page outlines to indicate that we can accept this drop
1398a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                showOutlines();
1399a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                layout.setHover(true);
1400a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                layout.onDragEnter();
1401a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
1402a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1403a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return true;
1404a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1405a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            break;
1406a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_LOCATION:
1407a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Visualize the drop location
1408a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1);
1409a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1410a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DROP:
1411a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Check if we have enough space on this screen to add a new shortcut
1412a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (!layout.findCellForSpan(pos, 1, 1)) {
1413a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                Toast.makeText(mContext, mContext.getString(R.string.out_of_space),
1414a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1415a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                return false;
1416a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1417a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1418a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Try and add any shortcuts
1419a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            int newDropCount = 0;
1420a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final LauncherModel model = mLauncher.getModel();
1421a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final ClipData data = event.getClipData();
1422a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            final int itemCount = data.getItemCount();
1423a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            for (int i = 0; i < itemCount; ++i) {
1424a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                final Intent intent = data.getItem(i).getIntent();
142555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                if (intent != null) {
142655cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    Object info = null;
142755cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    if (model.validateShortcutIntent(intent)) {
142855cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
142955cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    } else if (model.validateWidgetIntent(intent)) {
143055cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        final ComponentName component = ComponentName.unflattenFromString(
143155cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                            intent.getStringExtra(InstallWidgetReceiver.EXTRA_APPWIDGET_COMPONENT));
143255cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        final AppWidgetProviderInfo appInfo =
143355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                            model.findAppWidgetProviderInfoWithComponent(mContext, component);
143455cef262f97749300c2f6e764da0b00cbcb78879Winson Chung
143555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        PendingAddWidgetInfo createInfo = new PendingAddWidgetInfo();
143655cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
143755cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.componentName = appInfo.provider;
143855cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.minWidth = appInfo.minWidth;
143955cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.minHeight = appInfo.minHeight;
144055cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        createInfo.configurationData = intent.getParcelableExtra(
144155cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                                InstallWidgetReceiver.EXTRA_APPWIDGET_CONFIGURATION_DATA);
144255cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        info = createInfo;
144355cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    }
144455cef262f97749300c2f6e764da0b00cbcb78879Winson Chung
144555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    if (info != null) {
144655cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        onDropExternal(x, y, info, layout);
144755cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                        newDropCount++;
144855cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    }
1449a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                }
1450a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1451a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1452a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Show error message if we couldn't accept any of the items
1453a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            if (newDropCount <= 0) {
1454a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                Toast.makeText(mContext, "Only Shortcut Intents accepted.",
1455a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                        Toast.LENGTH_SHORT).show();
1456a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            }
1457a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
1458a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1459a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        case DragEvent.ACTION_DRAG_ENDED:
1460a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            // Hide the page outlines after the drop
1461a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.setHover(false);
1462a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            layout.onDragExit();
1463a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            hideOutlines();
1464a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung            return true;
1465a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        }
1466a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung        return super.onDragEvent(event);
1467a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung    }
1468a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
14694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
14704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
14714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
14724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
14734516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
14744516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
14754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy) {
14764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       mapPointFromSelfToChild(v, xy, null);
14774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
14784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
14794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
14804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
14814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
14824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
14834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
14844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * if cachedInverseMatrix is not null, this method will just use that matrix instead of
1485d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka    * computing it itself; we use this to avoid redundant matrix inversions in
14864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * findMatchingPageForDragOver
14874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
14884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
14894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
14904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       if (cachedInverseMatrix == null) {
14914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           v.getMatrix().invert(mTempInverseMatrix);
14924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           cachedInverseMatrix = mTempInverseMatrix;
14934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       }
14944516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] = xy[0] + mScrollX - v.getLeft();
14954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] = xy[1] + mScrollY - v.getTop();
14964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       cachedInverseMatrix.mapPoints(xy);
14974516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
14984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
14994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
15004516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15014516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from this CellLayout's coordinate space to
15024516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * the parent View's coordinate space. The argument xy is modified with the return result.
15034516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
15044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
15054516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromChildToSelf(View v, float[] xy) {
15064516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       v.getMatrix().mapPoints(xy);
15074516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] -= (mScrollX - v.getLeft());
15084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] -= (mScrollY - v.getTop());
15094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
15104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    static private float squaredDistance(float[] point1, float[] point2) {
15124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceX = point1[0] - point2[0];
15134516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceY = point2[1] - point2[1];
15144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return distanceX * distanceX + distanceY * distanceY;
15150280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
15160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
15174516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
15184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15194516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Returns true if the passed CellLayout cl overlaps with dragView
15204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
15224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    boolean overlaps(CellLayout cl, DragView dragView,
15234516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
15244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the coordinates of the item being dragged to the CellLayout's coordinates
15254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemTopLeft = mTempDragCoordinates;
15264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[0] = dragViewX + dragView.getScaledDragRegionXOffset();
15274516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[1] = dragViewY + dragView.getScaledDragRegionYOffset();
15284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
15294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getScaledDragRegionWidth();
15304516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getScaledDragRegionHeight();
15314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the dragged item's top left coordinates
15334516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // to the CellLayout's local coordinates
15344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
15354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
15364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
15374516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
15394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the dragged item's bottom right coordinates
15404516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // to the CellLayout's local coordinates
15414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
15424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
15434516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
15444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
15464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float overlap = (overlapRegionRight - overlapRegionLeft) *
15474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                         (overlapRegionBottom - overlapRegionTop);
15484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (overlap > 0) {
15494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    return true;
15504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                }
15514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka             }
15524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        }
15534516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return false;
15544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    }
1555a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
15564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
15574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * This method returns the CellLayout that is currently being dragged to. In order to drag
15594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
15604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
15614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Return null if no CellLayout is currently being dragged over
15634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
15644516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
15654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private CellLayout findMatchingPageForDragOver(
15664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            DragView dragView, int originX, int originY, int offsetX, int offsetY) {
15674516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which ones overlap
15684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // with the item being dragged and then choose the one that's closest to the touch point
1569a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
1570a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
15710280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float smallestDistSoFar = Float.MAX_VALUE;
15724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
1573a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
1574a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
1575a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
15764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            final float[] touchXy = mTempTouchCoordinates;
15774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[0] = originX + offsetX;
15784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[1] = originY + offsetY;
1579a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
15804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the touch coordinates to the CellLayout's local coordinates
15814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // If the touch point is within the bounds of the cell layout, we can return immediately
15820280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cl.getMatrix().invert(mTempInverseMatrix);
15834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
15844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
15864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
15874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                return cl;
15884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
15894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
15914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Get the center of the cell layout in screen coordinates
15924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
15934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[0] = cl.getWidth()/2;
15944516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[1] = cl.getHeight()/2;
15954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                mapPointFromChildToSelf(cl, cellLayoutCenter);
15964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
15974516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[0] = originX + offsetX;
15984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[1] = originY + offsetY;
15994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16004516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Calculate the distance between the center of the CellLayout
16014516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // and the touch point
16024516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float dist = squaredDistance(touchXy, cellLayoutCenter);
16034516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
16044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (dist < smallestDistSoFar) {
16050280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    smallestDistSoFar = dist;
1606a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
1607a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
16084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
1609a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1610a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
1611a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
1612a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1613440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1614440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
1615d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // When touch is inside the scroll area, skip dragOver actions for the current screen
1616d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mInScrollArea) {
1617d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            CellLayout layout;
1618d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originX = x - xOffset;
1619d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originY = y - yOffset;
1620d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mIsSmall || mIsInUnshrinkAnimation) {
1621d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = findMatchingPageForDragOver(
1622d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        dragView, originX, originY, xOffset, yOffset);
1623d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1624d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1625d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1626d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(false);
1627d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1628d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
1629d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1630d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(true);
1631d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1632d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1633d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            } else {
1634d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = getCurrentDropLayout();
1635d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1636d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                final ItemInfo item = (ItemInfo)dragInfo;
1637d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (dragInfo instanceof LauncherAppWidgetInfo) {
1638d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
1639d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1640d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (widgetInfo.spanX == -1) {
1641d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        // Calculate the grid spans needed to fit this widget
1642d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int[] spans = layout.rectToCell(
1643d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                widgetInfo.minWidth, widgetInfo.minHeight, null);
1644d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanX = spans[0];
1645d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanY = spans[1];
1646d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1647d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1648a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1649d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (source instanceof AllAppsPagedView) {
1650d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // This is a hack to fix the point used to determine which cell an icon from
1651d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // the all apps screen is over
1652d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (item != null && item.spanX == 1 && layout != null) {
1653d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
1654d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1655d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        originX += dragRegionLeft - dragView.getDragRegionLeft();
1656d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
1657d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            dragView.setDragRegion(dragView.getDragRegionLeft(),
1658d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionTop(),
1659d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    layout.getCellWidth(),
1660d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionHeight());
1661d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        }
1662d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1663a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
16641262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1665d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1666d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1667d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.onDragExit();
1668d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1669a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung                    layout.onDragEnter();
1670d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
16711262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                }
16726569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1673d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // only visualize the drop locations for moving icons within the home screen on
1674d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // tablet on phone, we also visualize icons dragged in from All Apps
1675d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if ((!LauncherApplication.isScreenXLarge() || source == this)
1676d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        && mDragTargetLayout != null) {
1677d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    final View child = (mDragInfo == null) ? null : mDragInfo.cell;
1678d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
1679d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
1680d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
1681d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            localOriginX, localOriginY, item.spanX, item.spanY);
1682d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
16831262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            }
1684976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
168531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
168631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1687aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
1688aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
16896569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
16900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mDragTargetLayout.onDragExit();
16916569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
16921262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mIsPageMoving) {
16931262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
16941b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen            mInDragMode = false;
16951262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
169608ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        clearAllHovers();
169731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
169831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1699aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1700aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
170131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
170231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1703aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
17042b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
17052b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
17062b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
17072b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
17082b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
17092b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
17102b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
17112b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
17122b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
17132b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
17140280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
171555cef262f97749300c2f6e764da0b00cbcb78879Winson Chung            onDropExternal(-1, -1, dragInfo, cl, false);
17162b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
17172b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
17180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mLauncher.showOutOfSpaceMessage();
17192b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
17202b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
17212b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
17220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    // Drag from somewhere else
17234be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // NOTE: This can also be called when we are outside of a drag event, when we want
17244be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // to add an item to one of the workspace screens.
1725aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1726aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
17270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int screen = indexOfChild(cellLayout);
17280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (dragInfo instanceof PendingAddItemInfo) {
17290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
17300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // When dragging and dropping from customization tray, we deal with creating
17310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // widgets/shortcuts/folders in a slightly different way
17320280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            int[] touchXY = new int[2];
17330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[0] = x;
17340280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[1] = y;
17350280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            switch (info.itemType) {
17360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
173755cef262f97749300c2f6e764da0b00cbcb78879Winson Chung                    mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) info, screen, touchXY);
17380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
17390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
17400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
17410280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
17420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
17430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
17440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
17450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                default:
17460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    throw new IllegalStateException("Unknown item type: " + info.itemType);
17470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
17480280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
174918014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
17500280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return;
17510280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
17520280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
17530280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        // This is for other drag/drop cases, like dragging from All Apps
175431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
175531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1756af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
175731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
175831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
175931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
176031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1761e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
176231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1763aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
176431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1765aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1766aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
176731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
176831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
176931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
1770c9a961952d1a057029874f8426b90181f6876034Michael Jurka                    cellLayout, (UserFolderInfo) info, mIconCache);
1771af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
177231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
17730280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            throw new IllegalStateException("Unknown item type: " + info.itemType);
177431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
177531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17766569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
17776569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
17780280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
17796569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
17807ded67cd64153cd41bb133a6aab11b3254b4a5d9Michael Jurka            mTargetCell = findNearestVacantArea(x, y, 1, 1, null, cellLayout, mTargetCell);
1781aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1782aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1783aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
178418014791be2e3f41080f0bf621c618e3f096c5c7Michael Jurka            cellLayout.animateDrop();
17856569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
178631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1787af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
17880280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1789aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1790af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
179131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1792aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
179370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
179470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
179570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
179670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
179770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
1798d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // if we're currently small, use findMatchingPageForDragOver instead
1799d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mIsSmall) return null;
18000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
180170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
180270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
180331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
180470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
18050280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * Return the current CellInfo describing our current drag; this method exists
18060280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * so that Launcher can sync this object with the correct info when the activity is created/
18070280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * destroyed
18080280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     *
18090280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     */
18100280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public CellLayout.CellInfo getDragInfo() {
18110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return mDragInfo;
18120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
18130280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
18140280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    /**
181570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
181670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
18176a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka    private int[] findNearestVacantArea(int pixelX, int pixelY,
181870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
18196569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
18205f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
18215f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelY = pixelY - (layout.getTop() - mScrollY);
18226569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
182370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
18240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return layout.findNearestVacantArea(
1825fc9f07d42511231a26fa182c32e2efaa0f41d478Michael Jurka                localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
182670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1827aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
18288f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
18298f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
18308f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
18318f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
18320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
18338f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
18348f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
183531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
183631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
183731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
183831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
183900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
184000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
184131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
184231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
184331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1844aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
184531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
184631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
184731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
184800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
184900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
185000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1851aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
185231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1853ce34a9768b01115def95f000a6a8f35870f10d3aPatrick Dubroy        } else if (mDragInfo != null) {
1854cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy            ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell);
185531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
185631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18574be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragOutline = null;
185831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
185931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
186031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
18620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return true;
18630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
18640280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
18650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
18660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
18670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
18680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
18690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
18700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
18710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
187231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
1873c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
18740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
187531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
187631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
187731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
187931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
1880c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
18810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
188231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
188331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1884138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
18851262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
18861262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onEnterScrollArea(int direction) {
1887d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
1888d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = true;
1889d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            final int screen = getCurrentPage() + ((direction == DragController.SCROLL_LEFT) ? -1 : 1);
1890d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (0 <= screen && screen < getChildCount()) {
1891d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                ((CellLayout) getChildAt(screen)).setHover(true);
1892d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
18931262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1894d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mDragTargetLayout != null) {
1895d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout.onDragExit();
1896d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout = null;
1897d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
18981262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
18991262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
19001262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
190108ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    private void clearAllHovers() {
190208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        final int childCount = getChildCount();
190308ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        for (int i = 0; i < childCount; i++) {
190408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            ((CellLayout) getChildAt(i)).setHover(false);
190508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        }
190608ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    }
190708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
19081262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
19091262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onExitScrollArea() {
1910d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mInScrollArea) {
1911d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = false;
191208ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            clearAllHovers();
19131262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
19141262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
19151262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
191631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1917dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
191831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
191931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
192031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
192131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
192231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
192331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
192431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
192531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
1926aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
192731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
192831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
192931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
193031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
193131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
193231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
193331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
193431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
193531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
193631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
193731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
193831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
193931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
194031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
194131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
194231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
194331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
194431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
194531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
194631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
194731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
194831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
194931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
195031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
195164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
1952dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
19535c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
1954629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
1955574d20ec84551370987dde530c27ec493bdef564Romain Guy
195664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
195764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
195864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
195964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
196064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
196164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
1962dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
196331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1964629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1965629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
1966629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
1967629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
1968629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
1969629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
1970aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1971629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
1972629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1973629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
1974629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
1975aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
19760589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
19770589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
1978629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
1979629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
1980aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
198164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
198264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
198364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
198464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
198564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
198664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
198764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1988629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1989629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
1990629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
19910589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
19920589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
1993629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
1994629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
1995aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1996629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
19970589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
1998629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
1999629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
2000aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
200164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
200264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
200364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
200464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
200573013bf94f49ffbacba2b8300f6a2dd4eeebbd13Brad Fitzpatrick                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
200664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
200764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
200864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
2009629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
2010629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2011aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2012629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
2013629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
2014629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
2015aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
2016aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
2017629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2018629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
2019629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
2020629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
2021629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
2022629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
2023629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
2024f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
202564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
202664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
202764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
2028aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
202964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
203064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
2031629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2032629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
2033629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
2034629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
2035629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
2036e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
203764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
203864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
203964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
2040aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
204164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
204264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
2043629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
2044574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
2045574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
2046aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2047629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
2048629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
2049629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
2050629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
2051629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
2052629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
2053629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
2054574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
2055aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
2056629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
2057629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
2058629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
20595c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
206031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
2061629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
206231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
206331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
2064f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
206564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
2066dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
2067dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
2068f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
2069f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
2070f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
2071f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
2072f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
20730589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
20740589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
2075f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
2076f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
2077f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
2078f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
2079f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
2080f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
208164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
208264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
2083aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
208464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
208564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
208664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
208764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
208864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
208964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
209064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
209164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
2092f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
2093f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
2094f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
2095f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
2096f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
2097f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
209814f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
2099c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
2100c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
2101c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        } else if (animate) {
2102c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            snapToPage(mDefaultPage);
2103c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
21040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
2105c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
21060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
210731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
210831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21098a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
21108a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
21118a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
21120142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
21130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
21148a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
21158a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
21160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
21170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
21180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
211931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
21210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
212231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
21230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
212431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
2125