Workspace.java revision 08ae2ec4847a971ad1b19c163e3a0d6307a8ed72
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
19472b281d5cb4f5660df981a6c912266b9f5703feChet Haaseimport android.animation.AnimatorListenerAdapter;
20af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport com.android.launcher.R;
21495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell
220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.Animator;
23de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroyimport android.animation.Animator.AnimatorListener;
24b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.AnimatorSet;
250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.ObjectAnimator;
260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.PropertyValuesHolder;
278f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.app.WallpaperManager;
28629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetManager;
29629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
30495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.ComponentName;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent;
33495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.pm.PackageManager;
345c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.content.pm.ProviderInfo;
357247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.content.res.Resources;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.TypedArray;
374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Bitmap;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Color;
40a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.graphics.Matrix;
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
424be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoimport android.graphics.Region.Op;
43f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.graphics.drawable.Drawable;
445c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.net.Uri;
45956091ba7863bd72086275e61084864994dd6fa7Joe Onoratoimport android.os.IBinder;
46495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcelable;
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
48291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandlerimport android.util.Log;
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
51f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
5231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
53af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.ArrayList;
54af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.HashSet;
55edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
59aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
6031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
62dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
63e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
643a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
66dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
67dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
68dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
69a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
70f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    // Y rotation to apply to the workspace screens
71f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final float WORKSPACE_ROTATION = 12.5f;
72a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
73a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // These are extra scale factors to apply to the mini home screens
74a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // so as to achieve the desired transform
75a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_0 = 0.97f;
76a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
77e54cec82a915c2bc8a7d719228c5d907f3fe14ecAdam Cohen    private static final float EXTRA_SCALE_FACTOR_2 = 1.08f;
78a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
79f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DELAY = 300;
80f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_OUT_DURATION = 300;
81f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private static final int BACKGROUND_FADE_IN_DURATION = 100;
82f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // These animators are used to fade the background
84472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeInAnimation;
85472b281d5cb4f5660df981a6c912266b9f5703feChet Haase    private ObjectAnimator mBackgroundFadeOutAnimation;
86f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    private float mBackgroundAlpha = 0;
87f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
888f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
89aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
9131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    private boolean mWaitingToShrinkToBottom = false;
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    private boolean mPageMoving = false;
9521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
100aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
10170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
10270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
10370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
10470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1066569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
1076569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
1086569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
1096569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
1106569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
1120589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
11300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
114aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // These are temporary variables to prevent having to allocate a new object just to
1164516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
11870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
1190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private float[] mTempOriginXY = new float[2];
120a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
1214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempTouchCoordinates = new float[2];
1224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private float[] mTempCellLayoutCenterCoordinates = new float[2];
123a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
1240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private Matrix mTempInverseMatrix = new Matrix();
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
126d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
127d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1298a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1308a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
131aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1321262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    // State variable that indicates whether the pages are small (ie when you're
133dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
134c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsSmall = false;
135c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka    private boolean mIsInUnshrinkAnimation = false;
136b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
1373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private enum ShrinkPosition {
1383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM_HIDDEN, SHRINK_TO_BOTTOM_VISIBLE };
1393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private ShrinkPosition mShrunkenState;
140dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
1411262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    private boolean mInScrollArea = false;
1421262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
1444be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap mDragOutline = null;
1454be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Rect mTempRect = new Rect();
1464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private int[] mTempXY = new int[2];
1474be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
16631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1685f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
1695f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
1705f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFadeInAdjacentScreens = false;
1715f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1738f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
174aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
175aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
176aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
177d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
178d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
1790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
182d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
1830d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
1840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
1910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
1920589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
1930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
1940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
1950589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
1960589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
198472b281d5cb4f5660df981a6c912266b9f5703feChet Haase        mUnshrinkAnimationListener = new AnimatorListenerAdapter() {
199c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            public void onAnimationStart(Animator animation) {
200c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = true;
201c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            }
202b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationEnd(Animator animation) {
203c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka                mIsInUnshrinkAnimation = false;
204dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
205dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
2060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
2070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
20931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
211f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected int getScrollMode() {
212f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        if (LauncherApplication.isScreenXLarge()) {
213f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.QUINTIC_MODE;
214f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        } else {
215f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            return SmoothPagedView.OVERSHOOT_MODE;
216f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
217f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
218f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
219f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
22031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
22421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
22631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
23321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
24431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
26021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        ((CellLayout) child).setOnInterceptTouchListener(this);
26131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
2710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
272aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
273aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
274aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
275aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
282dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
283dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
285dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
2860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
2870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
2890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
290aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
291aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
292aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
293aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
29631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
3030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
3090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
31031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3120142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
3130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
3140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
32031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
32631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
32731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
33131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
332aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
333aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
334aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
335aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
34031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
34131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
34231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
34331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
350291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
351291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
352291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
35931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
36031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
36131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
365aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3666569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
367845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka        int childId = LauncherModel.getCellLayoutChildId(-1, screen, x, y, spanX, spanY);
368aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
369aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
370aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
3716569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
372aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
373aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
374aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
37531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
3760d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
37831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
37900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
380aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
38100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
38231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
38331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
384dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
385dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
386c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
3872b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
38896226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
38921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        } else if (!mPageMoving) {
39021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            if (v == getChildAt(mCurrentPage - 1)) {
39121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage - 1);
39221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
39321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            } else if (v == getChildAt(mCurrentPage + 1)) {
39421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                snapToPage(mCurrentPage + 1);
39521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                return true;
39621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen            }
397dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
398dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
3990e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
4000e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
4015f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4025f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
403c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4045f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4055f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4065f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4075f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
4085f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4095f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4105f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
4115f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
412c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
4135f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
4145f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
4155f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
4165f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.onInterceptTouchEvent(ev);
4175f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
4185f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
4191262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageBeginMoving() {
4200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
4210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
42216fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage, mNextPage);
4230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4240142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
4250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
42616fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka            enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
42731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
428f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        showOutlines();
42921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = true;
43031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
43131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4321262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    protected void onPageEndMoving() {
43316fed41e5e680c547b23e108788eb85f1b04d36dMichael Jurka        clearChildrenCache();
4341262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        // Hide the outlines, as long as we're not dragging
4351262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mDragController.dragging()) {
4361262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
4371262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
43821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        mPageMoving = false;
4390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
4400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4410142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
4420142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
4430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
4440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
4460142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
4470142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
4480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
4550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
4560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
4570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4588f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
459798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
460798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
461798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
462798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
46386f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
46486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
46586f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
46686f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
46786f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
46886f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
46986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
47086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
47186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
472956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
4738f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
474aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
475f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void showOutlines() {
4763e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
4773e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
4783e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
479472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 1.0f);
480472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeInAnimation.setDuration(BACKGROUND_FADE_IN_DURATION);
4813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeInAnimation.start();
4823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
483f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
484f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
485f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void hideOutlines() {
4863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
4873e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeInAnimation != null) mBackgroundFadeInAnimation.cancel();
4883e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            if (mBackgroundFadeOutAnimation != null) mBackgroundFadeOutAnimation.cancel();
489472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation = ObjectAnimator.ofFloat(this, "backgroundAlpha", 0.0f);
490472b281d5cb4f5660df981a6c912266b9f5703feChet Haase            mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
4913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.setStartDelay(BACKGROUND_FADE_OUT_DELAY);
4923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            mBackgroundFadeOutAnimation.start();
4933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
494f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
495f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
496f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public void setBackgroundAlpha(float alpha) {
497f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        mBackgroundAlpha = alpha;
498f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
499f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            CellLayout cl = (CellLayout) getChildAt(i);
500f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            cl.setBackgroundAlpha(alpha);
501f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
502f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
503f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
504f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    public float getBackgroundAlpha() {
505f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        return mBackgroundAlpha;
506f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
507f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
508f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    @Override
509f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    protected void screenScrolled(int screenCenter) {
51021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        final int halfScreenSize = getMeasuredWidth() / 2;
51121f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        for (int i = 0; i < getChildCount(); i++) {
512f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            View v = getChildAt(i);
513f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            if (v != null) {
51421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int totalDistance = v.getMeasuredWidth() + mPageSpacing;
51521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                int delta = screenCenter - (getChildOffset(i) -
51621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                        getRelativeChildOffset(i) + halfScreenSize);
517f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
51821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float scrollProgress = delta/(totalDistance*1.0f);
51921f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.min(scrollProgress, 1.0f);
52021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                scrollProgress = Math.max(scrollProgress, -1.0f);
521f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
52221f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                float rotation = WORKSPACE_ROTATION * scrollProgress;
52321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen                v.setRotationY(rotation);
524f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            }
525f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen        }
526f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen    }
527f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
52800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
52900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
530956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
53100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
53200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
53300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
53431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
53528750fba6a2d141eb9a1e566718c17236030b815Michael Jurka    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
5360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
537aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
53879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
53979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
54079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mWaitingToShrinkToBottom) {
54179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            shrinkToBottom(false);
54279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = false;
54379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
54479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
545aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
546aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
547aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
5480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
549aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
55031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
55131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
55231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
554c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
5550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
5560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
5570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
5580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
5590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
5600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
5620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
5630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
5640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
56531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
56631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
56731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
56831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
56931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
570678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
57131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
57231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
57331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
57431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
5750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
57631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
57731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
57831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
57931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
58031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
58131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
582c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
583678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
58431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
5850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
58631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
5870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
5880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
58931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
59031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
59131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
59231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
59331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
5947bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
5957bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
59654dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
59754dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
5986b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
5997bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
6007bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
6017bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
6027bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
6037bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
6047bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
6050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
6060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
6070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
6080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
6090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
6103a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
611aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
612dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
613fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
6150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
616fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
6170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
61831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
61931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
62031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
62131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
62231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
62331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
62431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
625dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
626dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
62731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
62831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
62931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
63031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
63131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
63231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
63331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
6342bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
6352bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
6362bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
6372bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
6382bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
6393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            setCurrentPage(mCurrentPage);
6407c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
64131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
64231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
64431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
645aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
64601f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
64701f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
64801f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
64901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
6506b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
6510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
65201f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
65301f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
65401f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
6550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
656213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
657213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
658213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
65979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
66079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
66179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
66279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
66379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mFirstLayout) {
66479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
66579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
66679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
66779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // to get our width so we can layout the mini-screen views correctly
66879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = true;
66979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        } else {
6703e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, animated);
67179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
672213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
673213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
674a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float getYScaleForScreen(int screen) {
675a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int x = Math.abs(screen - 2);
676a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
677a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // TODO: This should be generalized for use with arbitrary rotation angles.
678a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        switch(x) {
679a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 0: return EXTRA_SCALE_FACTOR_0;
680a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 1: return EXTRA_SCALE_FACTOR_1;
681a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 2: return EXTRA_SCALE_FACTOR_2;
682a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
683a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        return 1.0f;
684a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
685a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
686dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
6870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
688dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
6893e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        mShrunkenState = shrinkPosition;
6903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
6913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        // Stop any scrolling, move to the current page right away
6923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        setCurrentPage(mCurrentPage);
6933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
6943e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
6955f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // we intercept and reject all touch events when we're small, so be sure to reset the state
6965f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mTouchState = TOUCH_STATE_REST;
6975f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mActivePointerId = INVALID_POINTER;
6985f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
6997247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
700dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
701213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
7020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
7040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
7050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
7060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
7070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
7080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
709a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
710dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
711dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
712a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
713213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
714213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        float newY = getResources().getDimension(R.dimen.smallScreenVerticalMargin);
7153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float finalAlpha = 1.0f;
7163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        float extraShrinkFactor = 1.0f;
7173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
7183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka             newY = screenHeight - newY - scaledPageHeight;
7193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
7203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // We shrink and disappear to nothing in the case of all apps
7223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            // (which is when we shrink to the bottom)
7230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
7243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            finalAlpha = 0.0f;
7253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            extraShrinkFactor = 0.1f;
7260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
727b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            newY = screenHeight / 2 - scaledPageHeight / 2;
728b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            finalAlpha = 1.0f;
729b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_TOP) {
730b0b2e6f588367cf40a4270cca81af7d78f8e382eWinson Chung            newY = screenHeight / 10;
731213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
732dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
733dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
734dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
735dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
736dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
7370142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
738a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
739a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // We are going to scale about the center of the view, so we need to adjust the positions
740a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // of the views accordingly
741a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newX -= (pageWidth - scaledPageWidth) / 2.0f;
742a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newY -= (pageHeight - scaledPageHeight) / 2.0f;
743dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
744dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
745a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
746f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen            float rotation = (-i + 2) * WORKSPACE_ROTATION;
747a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
748a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleY = getYScaleForScreen(i);
749a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
75079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
7517247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
752472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(cl,
753472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("x", newX),
754472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("y", newY),
755472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleX",
7563e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleX * extraShrinkFactor),
757472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("scaleY",
7583e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                                SHRINK_FACTOR * rotationScaleY * extraShrinkFactor),
759472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("backgroundAlpha", finalAlpha),
760472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("alpha", finalAlpha),
761472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                        PropertyValuesHolder.ofFloat("rotationY", rotation));
762472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.setDuration(duration);
763472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                anim.start();
76479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
76579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
76679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
767f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                cl.setScaleX(SHRINK_FACTOR * rotationScaleX);
768f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                cl.setScaleY(SHRINK_FACTOR * rotationScaleY);
7695f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                cl.setBackgroundAlpha(1.0f);
7703e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                cl.setAlpha(finalAlpha);
771a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                cl.setRotationY(rotation);
77279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
773dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
774a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            newX += scaledPageWidth + extraScaledSpacing;
775dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
776dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
777dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
778dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
7793e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7803e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDrops(ShrinkPosition state) {
7813e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, false, 1, 1);
7823e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
7833e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7843e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7853e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsDuringDrag(ShrinkPosition state, int spanX, int spanY) {
7863e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsHelper(state, true, spanX, spanY);
7873e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
7883e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7893e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    private void updateWhichPagesAcceptDropsHelper(
7903e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            ShrinkPosition state, boolean isDragHappening, int spanX, int spanY) {
7913e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        final int screenCount = getChildCount();
7923e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        for (int i = 0; i < screenCount; i++) {
7933e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
7943e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
7953e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            switch (state) {
7963e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_TOP:
7973e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
7983e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        boolean showDropHighlight = i == mCurrentPage;
7993e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        cl.setAcceptsDrops(showDropHighlight);
8003e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        break;
8013e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8023e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // otherwise, fall through below and mark non-full screens as accepting drops
8033e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_HIDDEN:
8043e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                case SHRINK_TO_BOTTOM_VISIBLE:
8053e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    if (!isDragHappening) {
8063e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // even if a drag isn't happening, we don't want to show a screen as
8073e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        // accepting drops if it doesn't have at least one free cell
8083e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanX = 1;
8093e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                        spanY = 1;
8103e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    }
8113e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    // the page accepts drops if we can find at least one empty spot
8123e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    cl.setAcceptsDrops(cl.findCellForSpan(null, spanX, spanY));
8133e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                    break;
8143e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                default:
8153e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                     throw new RuntimeException(
8163e7c7634531302271270c8cf418abc959d621cbcMichael Jurka                             "updateWhichPagesAcceptDropsHelper passed an unhandled ShrinkPosition");
8173e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            }
8183e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8193e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8203e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8213e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    /*
8223e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8233e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * We call these methods (onDragStartedWithItemSpans/onDragStartedWithItemMinSize) whenever we
8243e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * start a drag in Launcher, regardless of whether the drag has ever entered the Workspace
8253e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8263e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * These methods mark the appropriate pages as accepting drops (which alters their visual
8273e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     * appearance) and, if the pages are hidden, makes them visible.
8283e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     *
8293e7c7634531302271270c8cf418abc959d621cbcMichael Jurka     */
8303e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemSpans(int spanX, int spanY) {
8313e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDropsDuringDrag(mShrunkenState, spanX, spanY);
8323e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN) {
8333e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE, true);
8343e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8353e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8363e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8373e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStartedWithItemMinSize(int minWidth, int minHeight) {
8383e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        int[] spanXY = CellLayout.rectToCell(getResources(), minWidth, minHeight, null);
8393e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        onDragStartedWithItemSpans(spanXY[0], spanXY[1]);
8403e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8413e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
8423e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
8433e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    // never dragged over
8443e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    public void onDragStopped() {
8453e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        updateWhichPagesAcceptDrops(mShrunkenState);
8463e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        if (mShrunkenState == ShrinkPosition.SHRINK_TO_BOTTOM_VISIBLE) {
8473e7c7634531302271270c8cf418abc959d621cbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM_HIDDEN, true);
8483e7c7634531302271270c8cf418abc959d621cbcMichael Jurka        }
8493e7c7634531302271270c8cf418abc959d621cbcMichael Jurka    }
8503e7c7634531302271270c8cf418abc959d621cbcMichael Jurka
851dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
8522b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
8530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
8544cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
8554cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
8564cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
8570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
8584cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
8594cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
8600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
8614cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
8624cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
86321f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    @Override
86421f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    protected boolean handlePagingClicks() {
86521f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen        return true;
86621f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen    }
86721f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
8680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
869b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
8705f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
8715f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int delta = newX - mScrollX;
8724cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
873b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
874b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
875b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
876b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
877b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
8780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
879c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            unshrink();
880b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
881dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
882dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
8834cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
8844cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
8854cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
8864cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
8874cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
888b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
889c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mIsSmall = false;
890b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            AnimatorSet s = new AnimatorSet();
891b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
8924cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
8934cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
894b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
8957247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
8965f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
897f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                float rotation = 0.0f;
898f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
899f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                if (i < mCurrentPage) {
900f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = WORKSPACE_ROTATION;
901f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                } else if (i > mCurrentPage) {
902f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    rotation = -WORKSPACE_ROTATION;
903f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                }
904f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
9054cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
906472b281d5cb4f5660df981a6c912266b9f5703feChet Haase
9074cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    s.playTogether(
908472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationX", 0.0f).setDuration(duration),
909472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "translationY", 0.0f).setDuration(duration),
910472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleX", 1.0f).setDuration(duration),
911472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "scaleY", 1.0f).setDuration(duration),
912472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "backgroundAlpha", 0.0f).setDuration(duration),
913472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "alpha", finalAlphaValue).setDuration(duration),
914472b281d5cb4f5660df981a6c912266b9f5703feChet Haase                            ObjectAnimator.ofFloat(cl, "rotationY", rotation).setDuration(duration));
9154cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
9164cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
9174cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
9184cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
9194cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
9205f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setBackgroundAlpha(0.0f);
921f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setAlpha(finalAlphaValue);
922f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen                    cl.setRotationY(rotation);
9234cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
924b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
925c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            if (animated) {
926c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // If we call this when we're not animated, onAnimationEnd is never called on
927c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                // the listener; make sure we only use the listener when we're actually animating
928c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                s.addListener(mUnshrinkAnimationListener);
929c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka                s.start();
930c86756c20196e5c907df01fe0fc9193ffb934082Michael Jurka            }
931dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
932dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
933dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
9344be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
9354be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Draw the View v into the given Canvas.
9364be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     *
9374be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param v the view to draw
9384be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param destCanvas the canvas to draw on
9394be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * @param padding the horizontal and vertical padding to use when drawing
9404be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
9414be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private void drawDragView(View v, Canvas destCanvas, int padding) {
9424be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Rect clipRect = mTempRect;
9434be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.getDrawingRect(clipRect);
9444be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9454be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // For a TextView, adjust the clip rect so that we don't include the text label
9464be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        if (v instanceof TextView) {
9474be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            final int iconHeight = ((TextView)v).getCompoundPaddingTop() - v.getPaddingTop();
9484be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            clipRect.bottom = clipRect.top + iconHeight;
9494be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        }
9504be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9514be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // Draw the View into the bitmap.
9524be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The translate of scrollX and scrollY is necessary when drawing TextViews, because
9534be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // they set scrollX and scrollY to large values to achieve centered text
9544be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9554be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.save();
9564be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
9574be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.clipRect(clipRect, Op.REPLACE);
9584be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        v.draw(destCanvas);
9594be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        destCanvas.restore();
9604be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
9614be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9624be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
9634be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
9644be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
9654be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
9664be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {
9674be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
9684be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
9694be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
9704be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9714be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
9724be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
9734be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mOutlineHelper.applyExpensiveOuterOutline(b, canvas, outlineColor, true);
9744be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9754be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
9764be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
9774be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9784be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    /**
9794be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Returns a new bitmap to show when the given View is being dragged around.
9804be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     * Responsibility for the bitmap is transferred to the caller.
9814be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato     */
9824be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    private Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
9834be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int outlineColor = getResources().getColor(R.color.drag_outline_color);
9844be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = Bitmap.createBitmap(
9854be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                mDragOutline.getWidth(), mDragOutline.getHeight(), Bitmap.Config.ARGB_8888);
9864be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9874be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.setBitmap(b);
9884be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        canvas.drawBitmap(mDragOutline, 0, 0, null);
9894be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        drawDragView(v, canvas, padding);
9904be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mOutlineHelper.applyGlow(b, canvas, outlineColor);
9914be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
9924be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        return b;
9934be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    }
9944be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
99531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
99631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
9974be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int blurPadding = 40;
998aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
99931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
10007984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
100131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
100231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
1003aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
100431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
10050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
1006aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
100708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        CellLayout current = getCurrentDropLayout();
100831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
100931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
10104be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10114be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.clearFocus();
10124be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.setPressed(false);
10134be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10144be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Canvas canvas = new Canvas();
10154be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10164be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The outline is used to visualize where the item will land if dropped
10174be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragOutline = createDragOutline(child, canvas, blurPadding);
10184be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10194be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        // The drag bitmap follows the touch point around on the screen
10204be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final Bitmap b = createDragBitmap(child, canvas, blurPadding);
10214be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10224be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpWidth = b.getWidth();
10234be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int bmpHeight = b.getHeight();
10244be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.getLocationOnScreen(mTempXY);
10254be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
10264be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
10274be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
10284be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato                child.getTag(), DragController.DRAG_ACTION_MOVE, null);
10294be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        b.recycle();
10304be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
10314be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        child.setVisibility(View.GONE);
103231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
103331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10340280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
10350280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            boolean insertAtFirst, int intersectX, int intersectY) {
10360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
10370280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
103831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final int[] cellXY = new int[2];
10400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
10410280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
10420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
10430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
10440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellXY[0], cellXY[1]);
104531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
104631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
104800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
104900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
1050d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout == null) {
1051d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // cancel the drag if we're not over a screen at time of drop
1052d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // TODO: maybe add a nice fade here?
1053d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            return;
1054d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
1055a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originX = x - xOffset;
1056a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originY = y - yOffset;
1057c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
10580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
10590280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
10600280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
1061d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mapPointFromSelfToChild(mDragTargetLayout, mTempOriginXY);
10620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
10630280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
1064a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1065c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
106631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
1067d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
106831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
106931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Move internally
107031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragInfo != null) {
107131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final View cell = mDragInfo.cell;
1072a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
10736a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka                mTargetCell = findNearestVacantArea(originX, originY,
1074d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
1075aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        mTargetCell);
1076c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka
1077d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                int screen = indexOfChild(mDragTargetLayout);
1078c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                if (screen != mDragInfo.screen) {
1079c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                    final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
1080c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                    originalCellLayout.removeView(cell);
1081c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                    addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
1082c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                            mDragInfo.spanX, mDragInfo.spanY);
1083c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                }
1084d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout.onDropChild(cell);
108531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1086aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // update the item's position after drop
108784f296c106cb1c7b6d3ae6c6d5508a17f1324e29Romain Guy                final ItemInfo info = (ItemInfo) cell.getTag();
10880280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
1089d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
1090aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                lp.cellX = mTargetCell[0];
1091aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                lp.cellY = mTargetCell[1];
109260587efe1a60ed698db9e2cafcd48f2c3fc8aa40Michael Jurka                cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
1093845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka                        mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
1094aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
109531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                LauncherModel.moveItemInDatabase(mLauncher, info,
1096c6ee42e25f203e408826e7eab4ad8faf67ed2ff9Michael Jurka                        LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1097aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        lp.cellX, lp.cellY);
109831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
109931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
110031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
110131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1102aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
1103aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
110408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        mDragTargetLayout = null; // Reset the drag state
110508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
1106d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall) {
110708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            mDragTargetLayout = getCurrentDropLayout();
110808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            mDragTargetLayout.onDragEnter(dragView);
1109d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            showOutlines();
1110d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        }
111131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
111231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1113440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
11146569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            DragView dragView, Object dragInfo) {
11156569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1116c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1117d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // If we're shrunken, don't let anyone drag on folders/etc that are on the mini-screens
11180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return null;
11190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1120440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
1121440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
1122440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
1123440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
11246569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
1125440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
1126440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1127440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
1128440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
1129440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
1130440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
1131440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
1132440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
1133440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
1134440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
1135440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
1136440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
11370280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointX += mScrollX - currentLayout.getLeft();
11380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointY += mScrollY - currentLayout.getTop();
1139440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
1140440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
1141440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
1142440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
1143440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
1144440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
1145440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
1146440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
1147440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
1148440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
1149440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
1150440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
1151440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
1152440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
11536569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
11544516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
11554516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
11574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
11584516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11594516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
11604516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy) {
11614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       mapPointFromSelfToChild(v, xy, null);
11624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
11634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11644516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
11654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
11674516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * coordinate space. The argument xy is modified with the return result.
11684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * if cachedInverseMatrix is not null, this method will just use that matrix instead of
1170d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka    * computing it itself; we use this to avoid redundant matrix inversions in
11714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * findMatchingPageForDragOver
11724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11734516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
11744516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
11754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       if (cachedInverseMatrix == null) {
11764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           v.getMatrix().invert(mTempInverseMatrix);
11774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka           cachedInverseMatrix = mTempInverseMatrix;
11784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       }
11794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] = xy[0] + mScrollX - v.getLeft();
11804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] = xy[1] + mScrollY - v.getTop();
11814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       cachedInverseMatrix.mapPoints(xy);
11824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
11834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   /*
11854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * Convert the 2D coordinate xy from this CellLayout's coordinate space to
11874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    * the parent View's coordinate space. The argument xy is modified with the return result.
11884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    *
11894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    */
11904516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   void mapPointFromChildToSelf(View v, float[] xy) {
11914516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       v.getMatrix().mapPoints(xy);
11924516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[0] -= (mScrollX - v.getLeft());
11934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka       xy[1] -= (mScrollY - v.getTop());
11944516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka   }
11954516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
11964516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    static private float squaredDistance(float[] point1, float[] point2) {
11974516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceX = point1[0] - point2[0];
11984516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float distanceY = point2[1] - point2[1];
11994516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return distanceX * distanceX + distanceY * distanceY;
12000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
12010280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
12024516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
12034516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12044516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Returns true if the passed CellLayout cl overlaps with dragView
12054516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12064516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
12074516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    boolean overlaps(CellLayout cl, DragView dragView,
12084516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
12094516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the coordinates of the item being dragged to the CellLayout's coordinates
12104516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemTopLeft = mTempDragCoordinates;
12114516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[0] = dragViewX + dragView.getScaledDragRegionXOffset();
12124516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemTopLeft[1] = dragViewY + dragView.getScaledDragRegionYOffset();
12134516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
12144516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getScaledDragRegionWidth();
12154516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getScaledDragRegionHeight();
12164516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12174516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // Transform the dragged item's top left coordinates
12184516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // to the CellLayout's local coordinates
12194516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
12204516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
12214516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
12224516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12234516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
12244516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the dragged item's bottom right coordinates
12254516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // to the CellLayout's local coordinates
12264516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
12274516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
12284516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
12294516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12304516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
12314516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float overlap = (overlapRegionRight - overlapRegionLeft) *
12324516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                         (overlapRegionBottom - overlapRegionTop);
12334516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (overlap > 0) {
12344516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    return true;
12354516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                }
12364516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka             }
12374516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        }
12384516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        return false;
12394516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    }
1240a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
12414516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    /*
12424516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12434516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * This method returns the CellLayout that is currently being dragged to. In order to drag
12444516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
12454516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
12464516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12474516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     * Return null if no CellLayout is currently being dragged over
12484516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     *
12494516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka     */
12504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka    private CellLayout findMatchingPageForDragOver(
12514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            DragView dragView, int originX, int originY, int offsetX, int offsetY) {
12524516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which ones overlap
12534516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka        // with the item being dragged and then choose the one that's closest to the touch point
1254a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
1255a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
12560280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float smallestDistSoFar = Float.MAX_VALUE;
12574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
1258a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
1259a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
1260a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
12614516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            final float[] touchXy = mTempTouchCoordinates;
12624516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[0] = originX + offsetX;
12634516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            touchXy[1] = originY + offsetY;
1264a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
12654516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // Transform the touch coordinates to the CellLayout's local coordinates
12664516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            // If the touch point is within the bounds of the cell layout, we can return immediately
12670280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cl.getMatrix().invert(mTempInverseMatrix);
12684516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
12694516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12704516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
12714516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                    touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
12724516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                return cl;
12734516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
12744516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12754516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
12764516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Get the center of the cell layout in screen coordinates
12774516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
12784516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[0] = cl.getWidth()/2;
12794516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                cellLayoutCenter[1] = cl.getHeight()/2;
12804516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                mapPointFromChildToSelf(cl, cellLayoutCenter);
12814516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12824516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[0] = originX + offsetX;
12834516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                touchXy[1] = originY + offsetY;
12844516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12854516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // Calculate the distance between the center of the CellLayout
12864516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                // and the touch point
12874516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                float dist = squaredDistance(touchXy, cellLayoutCenter);
12884516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
12894516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka                if (dist < smallestDistSoFar) {
12900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    smallestDistSoFar = dist;
1291a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
1292a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
12934516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka            }
1294a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
1295a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
1296a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
1297a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1298440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
1299440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
1300d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // When touch is inside the scroll area, skip dragOver actions for the current screen
1301d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mInScrollArea) {
1302d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            CellLayout layout;
1303d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originX = x - xOffset;
1304d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            int originY = y - yOffset;
1305d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mIsSmall || mIsInUnshrinkAnimation) {
1306d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = findMatchingPageForDragOver(
1307d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        dragView, originX, originY, xOffset, yOffset);
1308d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1309d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1310d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1311d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(false);
1312d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1313d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
1314d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1315d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.setHover(true);
1316d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1317d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1318d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            } else {
1319d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                layout = getCurrentDropLayout();
1320d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1321d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                final ItemInfo item = (ItemInfo)dragInfo;
1322d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (dragInfo instanceof LauncherAppWidgetInfo) {
1323d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
1324d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1325d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (widgetInfo.spanX == -1) {
1326d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        // Calculate the grid spans needed to fit this widget
1327d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int[] spans = layout.rectToCell(
1328d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                widgetInfo.minWidth, widgetInfo.minHeight, null);
1329d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanX = spans[0];
1330d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        item.spanY = spans[1];
1331d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1332d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
1333a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1334d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (source instanceof AllAppsPagedView) {
1335d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // This is a hack to fix the point used to determine which cell an icon from
1336d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    // the all apps screen is over
1337d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (item != null && item.spanX == 1 && layout != null) {
1338d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        int dragRegionLeft = (dragView.getWidth() - layout.getCellWidth()) / 2;
1339d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1340d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        originX += dragRegionLeft - dragView.getDragRegionLeft();
1341d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        if (dragView.getDragRegionWidth() != layout.getCellWidth()) {
1342d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            dragView.setDragRegion(dragView.getDragRegionLeft(),
1343d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionTop(),
1344d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    layout.getCellWidth(),
1345d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                                    dragView.getDragRegionHeight());
1346d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        }
1347d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1348a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
13491262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1350d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if (layout != mDragTargetLayout) {
1351d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    if (mDragTargetLayout != null) {
1352d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        mDragTargetLayout.onDragExit();
1353d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    }
1354d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    layout.onDragEnter(dragView);
1355d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout = layout;
13561262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                }
13576569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1358d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // only visualize the drop locations for moving icons within the home screen on
1359d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                // tablet on phone, we also visualize icons dragged in from All Apps
1360d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                if ((!LauncherApplication.isScreenXLarge() || source == this)
1361d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                        && mDragTargetLayout != null) {
1362d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    final View child = (mDragInfo == null) ? null : mDragInfo.cell;
1363d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
1364d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
1365d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                    mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
1366d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                            localOriginX, localOriginY, item.spanX, item.spanY);
1367d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                }
13681262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            }
1369976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
137031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
137131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1372aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
1373aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
13746569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
13750280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mDragTargetLayout.onDragExit();
13766569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
13771262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        if (!mIsPageMoving) {
13781262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy            hideOutlines();
13791262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
138008ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        clearAllHovers();
138131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
138231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1383aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1384aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
138531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
138631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1387aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
13882b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
13892b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
13902b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
13912b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
13922b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
13932b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
13942b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
13952b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
13962b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
13972b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
13980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
13992b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            onDropExternal(0, 0, dragInfo, cl, false);
14002b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
14012b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
14020280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mLauncher.showOutOfSpaceMessage();
14032b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
14042b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
14052b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
14060280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    // Drag from somewhere else
14074be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // NOTE: This can also be called when we are outside of a drag event, when we want
14084be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    // to add an item to one of the workspace screens.
1409aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1410aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
14110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int screen = indexOfChild(cellLayout);
14120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (dragInfo instanceof PendingAddItemInfo) {
14130280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
14140280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // When dragging and dropping from customization tray, we deal with creating
14150280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // widgets/shortcuts/folders in a slightly different way
14160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            int[] touchXY = new int[2];
14170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[0] = x;
14180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[1] = y;
14190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            switch (info.itemType) {
14200280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
14210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addAppWidgetFromDrop(info.componentName, screen, touchXY);
14220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
14230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
14240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
14250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
14260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
14270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
14280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
14290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                default:
14300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    throw new IllegalStateException("Unknown item type: " + info.itemType);
14310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
14320280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
14330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return;
14340280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
14350280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
14360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        // This is for other drag/drop cases, like dragging from All Apps
143731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
143831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1439af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
144031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
144131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
144231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
144331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1444e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
144531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1446aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
144731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1448aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1449aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
145031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
145131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
145231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
14530280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    cellLayout, ((UserFolderInfo) info));
1454af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
145531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
14560280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            throw new IllegalStateException("Unknown item type: " + info.itemType);
145731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
145831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14596569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
14606569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
14610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
14626569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
14637ded67cd64153cd41bb133a6aab11b3254b4a5d9Michael Jurka            mTargetCell = findNearestVacantArea(x, y, 1, 1, null, cellLayout, mTargetCell);
1464aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1465aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1466aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
14676569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
146831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1469af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
14700280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1471aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1472af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
147331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1474aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
147570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
147670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
147770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
147870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
147970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
1480d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        // if we're currently small, use findMatchingPageForDragOver instead
1481d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mIsSmall) return null;
14820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
148370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
148470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
148531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
148670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
14870280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * Return the current CellInfo describing our current drag; this method exists
14880280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * so that Launcher can sync this object with the correct info when the activity is created/
14890280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * destroyed
14900280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     *
14910280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     */
14920280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public CellLayout.CellInfo getDragInfo() {
14930280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return mDragInfo;
14940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
14950280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
14960280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    /**
149770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * {@inheritDoc}
149870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
149970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    public boolean acceptDrop(DragSource source, int x, int y,
150000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
1501d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout == null) {
1502d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            // cancel the drag if we're not over a screen at time of drop
1503d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            return false;
15040280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1505d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka
1506c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final CellLayout.CellInfo dragCellInfo = mDragInfo;
1507c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1508c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
15094c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1510c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
15114c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1512d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
15130e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return true;
15140e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        } else {
15150280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mLauncher.showOutOfSpaceMessage();
15160e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return false;
15170e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        }
151870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1519aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
152070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
152170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
152270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
15236a1435d78d5133b1f37274c4d358bf6d22e10229Michael Jurka    private int[] findNearestVacantArea(int pixelX, int pixelY,
152470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
15256569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
15265f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
15275f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelY = pixelY - (layout.getTop() - mScrollY);
15286569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
152970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
15300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return layout.findNearestVacantArea(
1531fc9f07d42511231a26fa182c32e2efaa0f41d478Michael Jurka                localPixelX, localPixelY, spanX, spanY, ignoreView, recycle);
153270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1533aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
15348f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
15358f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
15368f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
15378f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
15380142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
15398f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
15408f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
154131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
154231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
154331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
154431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
154500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
154600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
154731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
154831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
154931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1550aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
155131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
155231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
155331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
155400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
155500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
155600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1557aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
155831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
155931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
156031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragInfo != null) {
156131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
156231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.onDropAborted(mDragInfo.cell);
156331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
156431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
156531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15664be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        if (mDragInfo != null) {
15674be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato            mDragInfo.cell.setVisibility(View.VISIBLE);
15684be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        }
15694be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato        mDragOutline = null;
157031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
157131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
157231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15730280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
15740280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return true;
15750280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
15760280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
15770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
15780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
15790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
15800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
15810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
15820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
15830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
158431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
1585c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
15860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
158731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
158831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
158931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
159131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
1592c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
15930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
159431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
159531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1596138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
15971262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
15981262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onEnterScrollArea(int direction) {
1599d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (!mIsSmall && !mIsInUnshrinkAnimation) {
1600d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = true;
1601d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            final int screen = getCurrentPage() + ((direction == DragController.SCROLL_LEFT) ? -1 : 1);
1602d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (0 <= screen && screen < getChildCount()) {
1603d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                ((CellLayout) getChildAt(screen)).setHover(true);
1604d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
16051262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1606d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            if (mDragTargetLayout != null) {
1607d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout.onDragExit();
1608d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka                mDragTargetLayout = null;
1609d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            }
16101262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
16111262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
16121262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
161308ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    private void clearAllHovers() {
161408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        final int childCount = getChildCount();
161508ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        for (int i = 0; i < childCount; i++) {
161608ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            ((CellLayout) getChildAt(i)).setHover(false);
161708ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy        }
161808ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy    }
161908ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy
16201262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    @Override
16211262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public void onExitScrollArea() {
1622d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka        if (mInScrollArea) {
1623d718d6a7ba424b600052a147e5633a201a04ccb7Michael Jurka            mInScrollArea = false;
162408ae2ec4847a971ad1b19c163e3a0d6307a8ed72Patrick Dubroy            clearAllHovers();
16251262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        }
16261262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
16271262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
162831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1629dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
163031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
163131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
163231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
163331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
163431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
163531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
163631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
163731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
1638aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
163931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
164031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
164131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
164231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
164331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
164431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
164531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
164631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
164731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
164831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
164931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
165031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
165131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
165231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
165331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
165431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
165531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
165631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
165731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
165831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
165931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
166031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
166131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
166231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
166364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
1664dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
16655c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
1666629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
1667574d20ec84551370987dde530c27ec493bdef564Romain Guy
166864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
166964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
167064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
167164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
167264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
167364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
1674dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
167531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1676629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1677629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
1678629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
1679629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
1680629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
1681629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
1682aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1683629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
1684629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1685629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
1686629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
1687aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
16880589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
16890589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
1690629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
1691629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
1692aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
169364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
169464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
169564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
169664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
169764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
169864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
169964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1700629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1701629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
1702629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
17030589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
17040589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
1705629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
1706629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
1707aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1708629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
17090589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
1710629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
1711629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
1712aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
171364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
171464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
171564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
171664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
171773013bf94f49ffbacba2b8300f6a2dd4eeebbd13Brad Fitzpatrick                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
171864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
171964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
172064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
1721629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
1722629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1723aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1724629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
1725629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
1726629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
1727aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
1728aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
1729629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1730629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
1731629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
1732629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
1733629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
1734629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
1735629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1736f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
173764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
173864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
173964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1740aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
174164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
174264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1743629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1744629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
1745629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
1746629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
1747629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
1748e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
174964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
175064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
175164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1752aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
175364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
175464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1755629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1756574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
1757574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1758aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1759629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
1760629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1761629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
1762629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
1763629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
1764629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
1765629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
1766574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1767aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1768629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
1769629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
1770629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
17715c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
177231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
1773629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
177431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
177531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1776f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
177764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
1778dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
1779dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
1780f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1781f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
1782f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
1783f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
1784f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
17850589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
17860589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
1787f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
1788f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
1789f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
1790f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
1791f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
1792f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
179364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
179464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
1795aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
179664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
179764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
179864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
179964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
180064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
180164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
180264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
180364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
1804f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
1805f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
1806f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
1807f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
1808f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
1809f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
181014f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
1811c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        if (mIsSmall || mIsInUnshrinkAnimation) {
1812c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
1813c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka        } else if (animate) {
1814c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka            snapToPage(mDefaultPage);
1815c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
18160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
1817c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
18180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
181931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
182031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18218a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
18228a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
18238a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
18240142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
18250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
18268a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
18278a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
18280142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
18290142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
18300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
183131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
18330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
183431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
183631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
1837