Workspace.java revision 0280c3be4d9f8fc6fdf015b7ecd276eb26f76f2d
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
19af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport com.android.launcher.R;
20495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell
210280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.Animator;
22b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.AnimatorSet;
230280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.ObjectAnimator;
240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.animation.PropertyValuesHolder;
25b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.Animator.AnimatorListener;
268f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornimport android.app.WallpaperManager;
27629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetManager;
28629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
29495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.ComponentName;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent;
32495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.content.pm.PackageManager;
335c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.content.pm.ProviderInfo;
347247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroyimport android.content.res.Resources;
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.res.TypedArray;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
37a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurkaimport android.graphics.Matrix;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
39f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.graphics.drawable.Drawable;
405c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guyimport android.net.Uri;
41956091ba7863bd72086275e61084864994dd6fa7Joe Onoratoimport android.os.IBinder;
42495f2892288504f4ab87e62957b3f71144dd73c2Adam Powellimport android.os.Parcelable;
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
44291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandlerimport android.util.Log;
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.ViewGroup;
48f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.widget.TextView;
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
50af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.ArrayList;
51af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.HashSet;
52edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
56aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
59dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
60e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
613a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
63dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
64dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
65dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
66a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
67a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // The maximum Y rotation to apply to the mini home screens
68a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float MINI_PAGE_MAX_ROTATION = 25.0f;
69a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
70a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // These are extra scale factors to apply to the mini home screens
71a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    // so as to achieve the desired transform
72a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_0 = 0.97f;
73a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private static final float EXTRA_SCALE_FACTOR_1 = 1.0f;
74e54cec82a915c2bc8a7d719228c5d907f3fe14ecAdam Cohen    private static final float EXTRA_SCALE_FACTOR_2 = 1.08f;
75a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private enum ShrinkPosition { SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM };
7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
788f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
79aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
8279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    private boolean mWaitingToShrinkToBottom = false;
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
8631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
88aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
8970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
9070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
9170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
9270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
946569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
956569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
966569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
976569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
986569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
1000589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
10100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
102aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
10470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
1050280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private float[] mTempOriginXY = new float[2];
106a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
107a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
1080280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private Matrix mTempInverseMatrix = new Matrix();
10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
110d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
111d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1138a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1148a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
115aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    // State variable that indicated whether the pages are small (ie when you're
117dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
118dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private boolean mIsSmall;
119b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
120dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1415f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
1425f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
1435f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            mFadeInAdjacentScreens = false;
1445f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
14531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1468f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
147aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
148aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
149aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
150d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
151d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
1520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
155d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
1560d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
1570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
1640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
1650589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
1660142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
1670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
1680589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
1690589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
171b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase        mUnshrinkAnimationListener = new AnimatorListener() {
172b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationStart(Animator animation) {}
173b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationEnd(Animator animation) {
174dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                mIsSmall = false;
175dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
176b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationCancel(Animator animation) {}
177b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationRepeat(Animator animation) {}
178dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
1790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
1800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
19231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
19331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
19631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
19831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
20031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
20231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
20331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
20431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
20531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
20631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
20931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
21031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
21131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
21231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
21331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
21431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
21831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
21931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
22031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
22631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2270142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2280142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
2300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
231aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
232aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
233aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
234aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
241dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
242dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
244dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
2450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
2460142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
2480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
249aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
250aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
251aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
252aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
2620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
2680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
2700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
2710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
2720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
2730142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
28231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
29031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
291aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
292aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
293aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
294aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
29631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
30131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
30231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
309291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
310291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
311291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
31731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
32031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
324aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3256569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
326d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int childId = LauncherModel.getCellLayoutChildId(child.getId(), screen, x, y, spanX, spanY);
327aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
328aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
329aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
3306569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
331aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
332aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
333aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
3350d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
33800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
339aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
34000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
34131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
34231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
343dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
344dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
345dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        if (mIsSmall) {
3462b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
34796226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
348dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
349dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
3500e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
3510e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
3525f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
3535f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean dispatchUnhandledMove(View focused, int direction) {
3545f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (mIsSmall) {
3555f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
3565f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
3575f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
3585f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.dispatchUnhandledMove(focused, direction);
3595f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
3605f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
3615f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    @Override
3625f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    public boolean onInterceptTouchEvent(MotionEvent ev) {
3635f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (mIsSmall) {
3645f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // when the home screens are shrunken, shouldn't allow side-scrolling
3655f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            return false;
3665f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
3675f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        return super.onInterceptTouchEvent(ev);
3685f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    }
3695f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
3700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void pageBeginMoving() {
3710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
3720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
3735f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // there's an issue where the alpha of neighboring pages doesn't get updated
3745f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // if drawing cache is enabled on children-- we only use that on xlarge devices,
3755f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            // so disable drawing cache in those cases
3765f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            if (!LauncherApplication.isScreenXLarge()) {
3775f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                enableChildrenCache(mCurrentPage, mNextPage);
3785f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            }
3790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
3800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
3810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
3825f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            if (!LauncherApplication.isScreenXLarge()) {
3835f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
3845f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            }
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void pageEndMoving() {
3895f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        if (!LauncherApplication.isScreenXLarge()) {
3905f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            clearChildrenCache();
3915f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        }
3920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
3930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
3940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
3960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
3970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
3980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
3990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
4000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
4010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
4080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
4090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
4100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4118f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
412798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
413798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
414798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
415798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
41686f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
41786f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
41886f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
41986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
42086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
42186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
42286f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
42386f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
42486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
425956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
4268f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
427aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
42800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
42900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
430956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
43100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
43200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
43300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
43431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
4350280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
4360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
437aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
43879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
43979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
44079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mWaitingToShrinkToBottom) {
44179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            shrinkToBottom(false);
44279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = false;
44379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
44479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
445aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
446aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
447aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
4480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
449aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
45031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
45131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
45231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
4530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
4540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mIsSmall) {
4550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
4560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
4570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
4580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
4590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
4600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
4620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
46531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
46631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
46731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
46831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
46931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
470678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
47131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
47231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
47331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
47431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
4750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
47631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
47731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
47831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
47931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
48031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
48131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
482c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
483678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
48431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
4850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
48631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
4870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
4880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
48931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
49031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
49131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
49231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
49331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
4947bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
4957bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
49654dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
49754dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
4986b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
4997bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
5007bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
5017bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
5027bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
5037bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
5047bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
5050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
5060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
5070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
5080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
5090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
5103a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
511aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
512dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
513fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
5140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
5150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
516fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
5170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
51831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
51931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
52031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
52131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
52231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
52331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
52431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
525dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
526dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
52731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
52831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
52931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
53031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
53131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
53231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
53331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
5342bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
5352bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
5362bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
5372bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
5382bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
5390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            snapToPage(mCurrentPage);
5407c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
54131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
54231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
54431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
545aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
54601f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
54701f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
54801f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
54901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
5506b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
5510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
55201f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
55301f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
55401f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
5550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
556213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
557213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
558213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
55979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
56079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
56179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
56279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
56379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mFirstLayout) {
56479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
56579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
56679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
56779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // to get our width so we can layout the mini-screen views correctly
56879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = true;
56979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        } else {
5700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM, animated);
57179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
572213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
573213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
574a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    private float getYScaleForScreen(int screen) {
575a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        int x = Math.abs(screen - 2);
576a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
577a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // TODO: This should be generalized for use with arbitrary rotation angles.
578a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        switch(x) {
579a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 0: return EXTRA_SCALE_FACTOR_0;
580a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 1: return EXTRA_SCALE_FACTOR_1;
581a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            case 2: return EXTRA_SCALE_FACTOR_2;
582a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        }
583a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        return 1.0f;
584a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    }
585a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
586dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
5870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
588dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
5895f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        // we intercept and reject all touch events when we're small, so be sure to reset the state
5905f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mTouchState = TOUCH_STATE_REST;
5915f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        mActivePointerId = INVALID_POINTER;
5925f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
5937247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
594dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
595213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
5960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
5980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
5990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
6000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
6020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
603a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        final float extraScaledSpacing = res.getDimension(R.dimen.smallScreenExtraSpacing);
604dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
605dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
606a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * extraScaledSpacing;
607213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
608213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        float newY = getResources().getDimension(R.dimen.smallScreenVerticalMargin);
6090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM) {
6100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
6110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
6120142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight / 2 - scaledPageHeight / 2;
613213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
614dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
615dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
616dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
617dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
618dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
6190142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
620a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
621a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // We are going to scale about the center of the view, so we need to adjust the positions
622a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        // of the views accordingly
623a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newX -= (pageWidth - scaledPageWidth) / 2.0f;
624a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen        newY -= (pageHeight - scaledPageHeight) / 2.0f;
625dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
626dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
627a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
628a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotation = (-i + 2) * MINI_PAGE_MAX_ROTATION / 2.0f;
629a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
630a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            float rotationScaleY = getYScaleForScreen(i);
631a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
63279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
6337247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
6345f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                new ObjectAnimator<Float>(duration, cl,
6355f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                        new PropertyValuesHolder<Float>("x", newX),
6365f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                        new PropertyValuesHolder<Float>("y", newY),
637e54cec82a915c2bc8a7d719228c5d907f3fe14ecAdam Cohen                        new PropertyValuesHolder<Float>("scaleX", SHRINK_FACTOR * rotationScaleX),
638e54cec82a915c2bc8a7d719228c5d907f3fe14ecAdam Cohen                        new PropertyValuesHolder<Float>("scaleY", SHRINK_FACTOR * rotationScaleY),
6395f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                        new PropertyValuesHolder<Float>("backgroundAlpha", 1.0f),
6405f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                        new PropertyValuesHolder<Float>("alpha", 0.0f),
6415f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                        new PropertyValuesHolder<Float>("rotationY", rotation)).start();
64279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
64379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
64479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
64579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setScaleX(SHRINK_FACTOR);
64679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setScaleY(SHRINK_FACTOR);
6475f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                cl.setBackgroundAlpha(1.0f);
6485f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                cl.setAlpha(0.0f);
649a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                cl.setRotationY(rotation);
65079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
651dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
652a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen            newX += scaledPageWidth + extraScaledSpacing;
653dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            cl.setOnInterceptTouchListener(this);
654dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
655dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
656dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
657dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
658dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
6592b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
6600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
6614cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
6624cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
6634cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
6640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
6654cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
6664cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
6670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
6684cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
6694cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
6700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
671b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
6725f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int newX = getChildOffset(newCurrentPage) - getRelativeChildOffset(newCurrentPage);
6735f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int delta = newX - mScrollX;
6744cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
675b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
676b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
677b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
678b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
679b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
6800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            snapToPage(newCurrentPage);
681b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            unshrink();
6820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
684b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
685dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
686dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
6874cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
6884cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
6894cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
6904cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
6914cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
692b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
693b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            AnimatorSet s = new AnimatorSet();
694b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
6954cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
6964cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
697b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
6987247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
6995f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                float finalAlphaValue = (i == mCurrentPage) ? 1.0f : 0.0f;
7004cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
7014cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    s.playTogether(
702b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "translationX", 0.0f),
703b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "translationY", 0.0f),
704b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "scaleX", 1.0f),
705b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "scaleY", 1.0f),
7065f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                            new ObjectAnimator<Float>(duration, cl, "backgroundAlpha", 0.0f),
7075f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                            new ObjectAnimator<Float>(duration, cl, "alpha", finalAlphaValue),
708a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                            new ObjectAnimator<Float>(duration, cl, "rotationY", 0.0f));
7094cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
7104cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
7114cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
7124cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
7134cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
7145f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setBackgroundAlpha(0.0f);
7155f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka                    cl.setAlpha(1.0f);
716a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen                    cl.setRotationY(0.0f);
7174cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
718b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
719b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            s.addListener(mUnshrinkAnimationListener);
720b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            s.start();
721dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
722dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
723dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
72431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
72531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
726aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
72731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
7287984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
72931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
73031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
731aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
73231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
7330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
734aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
7350142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout current = ((CellLayout) getChildAt(mCurrentPage));
73631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
73731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
73800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
73931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        invalidate();
74031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
74131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
7430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            boolean insertAtFirst, int intersectX, int intersectY) {
7440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final CellLayout cellLayout = (CellLayout) getChildAt(screen);
7450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        View view = mLauncher.createShortcut(R.layout.application, cellLayout, (ShortcutInfo) info);
74631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final int[] cellXY = new int[2];
7480280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        cellLayout.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
7490280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        addInScreen(view, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
7500280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
7510280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
7520280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellXY[0], cellXY[1]);
75331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
75431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7550280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
75600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
75700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
7580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        CellLayout cellLayout;
759a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originX = x - xOffset;
760a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originY = y - yOffset;
761a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (mIsSmall) {
7620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout = findMatchingPageForDragOver(dragView, originX, originY);
763a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (cellLayout == null) {
764a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                // cancel the drag if we're not over a mini-screen at time of drop
765a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                // TODO: maybe add a nice fade here?
766a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                return;
767a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
7680280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
7690280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
7700280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
7710280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mapPointGlobalToLocal(cellLayout, mTempOriginXY);
7720280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
7730280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
7740280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        } else {
7750280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout = getCurrentDropLayout();
776a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
77731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
778a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            onDropExternal(originX, originY, dragInfo, cellLayout);
77931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
78031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Move internally
78131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragInfo != null) {
78231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final View cell = mDragInfo.cell;
7830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
78452d9cb32608e7c3d065b4fb8e97269e238f1683eRomain Guy                if (index != mDragInfo.screen) {
78531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
78631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    originalCellLayout.removeView(cell);
787aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    addInScreen(cell, index, mDragInfo.cellX, mDragInfo.cellY,
788aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                            mDragInfo.spanX, mDragInfo.spanY);
78931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
790a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
791a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                mTargetCell = estimateDropCell(originX, originY,
792aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout,
793aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        mTargetCell);
794aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                cellLayout.onDropChild(cell);
79531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
796aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // update the item's position after drop
79784f296c106cb1c7b6d3ae6c6d5508a17f1324e29Romain Guy                final ItemInfo info = (ItemInfo) cell.getTag();
7980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
7990280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                cellLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
800aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                lp.cellX = mTargetCell[0];
801aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                lp.cellY = mTargetCell[1];
802aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
80331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                LauncherModel.moveItemInDatabase(mLauncher, info,
804aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        LauncherSettings.Favorites.CONTAINER_DESKTOP, index,
805aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        lp.cellX, lp.cellY);
80631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
80731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
80831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
80931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
810aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
811aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
81231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
81331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
814440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
8156569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            DragView dragView, Object dragInfo) {
8166569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
8170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (mIsSmall) {
8180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // If we're shrunken, don't let anyone drag on folders/etc  that are on the mini-screens
8190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return null;
8200280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
821440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
822440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
823440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
824440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
8256569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
826440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
827440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
828440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
829440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
830440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
831440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
832440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
833440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
834440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
835440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
836440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
837440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
8380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointX += mScrollX - currentLayout.getLeft();
8390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        dragPointY += mScrollY - currentLayout.getTop();
840440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
841440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
842440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
843440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
844440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
845440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
846440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
847440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
848440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
849440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
850440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
851440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
852440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
853440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
8546569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
8550280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
8560280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private void mapPointGlobalToLocal(View v, float[] xy) {
8570280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        xy[0] = xy[0] + mScrollX - v.getLeft();
8580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        xy[1] = xy[1] + mScrollY - v.getTop();
8590280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        v.getMatrix().invert(mTempInverseMatrix);
8600280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mTempInverseMatrix.mapPoints(xy);
8610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
8620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
863a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // xy = upper left corner of item being dragged
864a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // bottomRightXy = lower right corner of item being dragged
865a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // This method will see which mini-screen is most overlapped by the item being dragged, and
866a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // return it. It will also transform the parameters xy and bottomRightXy into the local
867a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // coordinate space of the returned screen
8680280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    private CellLayout findMatchingPageForDragOver(DragView dragView, int originX, int originY) {
8690280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float x = originX + dragView.getScaledDragRegionXOffset();
8700280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float y = originY + dragView.getScaledDragRegionYOffset();
8710280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float right = x + dragView.getScaledDragRegionWidth();
8720280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float bottom = y + dragView.getScaledDragRegionHeight();
873a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
874a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which one overlaps the most
875a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        // with the item being dragged.
876a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
877a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
8780280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        float smallestDistSoFar = Float.MAX_VALUE;
8790280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final float[] xy = mTempDragCoordinates;
8800280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        final float[] bottomRightXy = mTempDragBottomRightCoordinates;
881a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
882a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
883a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // Transform the coordinates of the item being dragged to the CellLayout's coordinates
884a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float left = cl.getLeft();
885a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float top = cl.getTop();
886a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            xy[0] = x + mScrollX - left;
887a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            xy[1] = y + mScrollY - top;
888a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
889a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            bottomRightXy[0] = right + mScrollX - left;
890a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            bottomRightXy[1] = bottom + mScrollY - top;
891a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
8920280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cl.getMatrix().invert(mTempInverseMatrix);
8930280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempInverseMatrix.mapPoints(xy);
8940280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempInverseMatrix.mapPoints(bottomRightXy);
895a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
896a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float dragRegionX = xy[0];
897a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float dragRegionY = xy[1];
898a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float dragRegionRight = bottomRightXy[0];
899a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float dragRegionBottom = bottomRightXy[1];
9000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            float dragRegionCenterX = (dragRegionX + dragRegionRight) / 2.0f;
9010280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            float dragRegionCenterY = (dragRegionY + dragRegionBottom) / 2.0f;
902a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
903a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // Find the overlapping region
904a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float overlapLeft = Math.max(0f, dragRegionX);
905a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float overlapTop = Math.max(0f, dragRegionY);
906a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float overlapBottom = Math.min(cl.getHeight(), dragRegionBottom);
907a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float overlapRight = Math.min(cl.getWidth(), dragRegionRight);
908a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (overlapRight >= 0 && overlapLeft <= cl.getWidth() &&
9090280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    (overlapTop >= 0 && overlapBottom <= cl.getHeight())) {
9100280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                // Calculate the distance between the two centers
9110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                float distX = dragRegionCenterX - cl.getWidth()/2;
9120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                float distY = dragRegionCenterY - cl.getHeight()/2;
9130280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                float dist = distX * distX + distY * distY;
9140280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
915a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                float overlap = (overlapRight - overlapLeft) * (overlapBottom - overlapTop);
9160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
9170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                // Calculate the closest overlapping region
9180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                if (overlap > 0 && dist < smallestDistSoFar) {
9190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    smallestDistSoFar = dist;
920a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
921a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
922a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka             }
923a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
9240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
9250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (bestMatchingScreen != mDragTargetLayout) {
926a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (mDragTargetLayout != null) {
9270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                mDragTargetLayout.onDragExit();
928a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
929a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            mDragTargetLayout = bestMatchingScreen;
930a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
931a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
932a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
933a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
934440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
935440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
9360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        CellLayout currentLayout;
9370280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int originX = x - xOffset;
9380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int originY = y - yOffset;
9390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (mIsSmall) {
9400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            currentLayout = findMatchingPageForDragOver(dragView, originX, originY);
9410280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
9420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            if (currentLayout == null) {
9430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                return;
9440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
9450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
9460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            currentLayout.setHover(true);
9470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // get originX and originY in the local coordinate system of the screen
9480280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[0] = originX;
9490280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mTempOriginXY[1] = originY;
9500280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mapPointGlobalToLocal(currentLayout, mTempOriginXY);
9510280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originX = (int)mTempOriginXY[0];
9520280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            originY = (int)mTempOriginXY[1];
9530280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        } else {
9540280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            currentLayout = getCurrentDropLayout();
9550280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
956440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
957976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        final ItemInfo item = (ItemInfo)dragInfo;
9586569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
9596569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (dragInfo instanceof LauncherAppWidgetInfo) {
9606569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
9616569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
9626569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            if (widgetInfo.spanX == -1) {
9636569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                // Calculate the grid spans needed to fit this widget
9648f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy                int[] spans = currentLayout.rectToCell(widgetInfo.minWidth, widgetInfo.minHeight, null);
9656569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                item.spanX = spans[0];
9666569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                item.spanY = spans[1];
9676569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            }
9686569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
969a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
970a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (source != this) {
971a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // This is a hack to fix the point used to determine which cell an icon from the all
972a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // apps screen is over
973a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (item != null && item.spanX == 1 && currentLayout != null) {
974a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                int dragRegionLeft = (dragView.getWidth() - currentLayout.getCellWidth()) / 2;
975a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
976a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                originX += dragRegionLeft - dragView.getDragRegionLeft();
977a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                if (dragView.getDragRegionWidth() != currentLayout.getCellWidth()) {
978a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    dragView.setDragRegion(dragView.getDragRegionLeft(), dragView.getDragRegionTop(),
979a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                            currentLayout.getCellWidth(), dragView.getDragRegionHeight());
980a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
981a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
982a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
9836569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (currentLayout != mDragTargetLayout) {
9846569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            if (mDragTargetLayout != null) {
9850280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                mDragTargetLayout.onDragExit();
9866569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            }
9876569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            mDragTargetLayout = currentLayout;
9886569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
9896569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
990a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        // only visualize the drop locations for moving icons within the home screen on tablet
991a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        // on phone, we also visualize icons dragged in from All Apps
992a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if ((!LauncherApplication.isScreenXLarge() || source == this)
993a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                && mDragTargetLayout != null) {
994a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            final View child = (mDragInfo == null) ? null : mDragInfo.cell;
9955f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int localOriginX = originX - (mDragTargetLayout.getLeft() - mScrollX);
9965f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka            int localOriginY = originY - (mDragTargetLayout.getTop() - mScrollY);
997a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            mDragTargetLayout.visualizeDropLocation(
9980280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    child, localOriginX, localOriginY, item.spanX, item.spanY, child);
999976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
100031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
100131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1002aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
1003aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
10046569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
10050280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mDragTargetLayout.onDragExit();
10066569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            mDragTargetLayout = null;
10076569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
100831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
100931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1010aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1011aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
101231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
101331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1014aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
10152b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
10162b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
10172b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
10182b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
10192b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
10202b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
10212b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
10222b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
10232b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
10242b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
10250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (cl.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
10262b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            onDropExternal(0, 0, dragInfo, cl, false);
10272b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
10282b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
10290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        mLauncher.showOutOfSpaceMessage();
10302b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
10312b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
10322b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
10330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    // Drag from somewhere else
1034aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
1035aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
10360280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        int screen = indexOfChild(cellLayout);
10370280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (dragInfo instanceof PendingAddItemInfo) {
10380280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            PendingAddItemInfo info = (PendingAddItemInfo) dragInfo;
10390280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // When dragging and dropping from customization tray, we deal with creating
10400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            // widgets/shortcuts/folders in a slightly different way
10410280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            int[] touchXY = new int[2];
10420280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[0] = x;
10430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            touchXY[1] = y;
10440280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            switch (info.itemType) {
10450280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
10460280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addAppWidgetFromDrop(info.componentName, screen, touchXY);
10470280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
10480280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
10490280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.addLiveFolderFromDrop(info.componentName, screen, touchXY);
10500280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
10510280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
10520280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    mLauncher.processShortcutFromDrop(info.componentName, screen, touchXY);
10530280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    break;
10540280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                default:
10550280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    throw new IllegalStateException("Unknown item type: " + info.itemType);
10560280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
10570280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
10580280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            return;
10590280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
10600280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
10610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        // This is for other drag/drop cases, like dragging from All Apps
106231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
106331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1064af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
106531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
106631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
106731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
106831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1069e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
107031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1071aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
107231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1073aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1074aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
107531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
107631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
107731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
10780280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    cellLayout, ((UserFolderInfo) info));
1079af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
108031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
10810280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            throw new IllegalStateException("Unknown item type: " + info.itemType);
108231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
108331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10846569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
10856569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
10860280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            cellLayout.onDragExit();
10876569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
10886569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
1089aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1090aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1091aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
10926569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
109331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1094af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
10950280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
1096aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1097af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
109831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1099aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
110070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
110170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
110270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
110370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
110470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
11050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
110670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
110770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
110831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
110970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
11100280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * Return the current CellInfo describing our current drag; this method exists
11110280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * so that Launcher can sync this object with the correct info when the activity is created/
11120280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     * destroyed
11130280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     *
11140280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka     */
11150280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public CellLayout.CellInfo getDragInfo() {
11160280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return mDragInfo;
11170280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
11180280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
11190280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    /**
112070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * {@inheritDoc}
112170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
112270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    public boolean acceptDrop(DragSource source, int x, int y,
112300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
11240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        CellLayout layout;
11250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (mIsSmall) {
11260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            layout = findMatchingPageForDragOver(dragView, x - xOffset, y - yOffset);
11270280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            if (layout == null) {
11280280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                // cancel the drag if we're not over a mini-screen at time of drop
11290280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                return false;
11300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            }
11310280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        } else {
11320280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            layout = getCurrentDropLayout();
11330280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        }
1134c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final CellLayout.CellInfo dragCellInfo = mDragInfo;
1135c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1136c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
11374c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1138c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
11394c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
11400280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        if (layout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
11410e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return true;
11420e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        } else {
11430280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            mLauncher.showOutOfSpaceMessage();
11440e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return false;
11450e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        }
114670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1147aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
114870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
114970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
115070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
1151263e019baafb3b6cbcfdef9c81d74a4bea769180Romain Guy    private int[] estimateDropCell(int pixelX, int pixelY,
115270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
11536569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
11546569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        final int[] cellXY = mTempCell;
11555f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelX = pixelX - (layout.getLeft() - mScrollX);
11565f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        int localPixelY = pixelY - (layout.getTop() - mScrollY);
11575f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka        layout.estimateDropCell(localPixelX, localPixelY, spanX, spanY, cellXY);
11586569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        layout.cellToPoint(cellXY[0], cellXY[1], mTempEstimate);
11596569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
116070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
11610280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return layout.findNearestVacantArea(
11620280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                mTempEstimate[0], mTempEstimate[1], spanX, spanY, recycle);
116370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1164aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
11658f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
11668f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
11678f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
11688f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
11690142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
11708f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
11718f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
117231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
117331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
117431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
117531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
117600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
117700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
117831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
117931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
118031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1181aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
118231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
118331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
118431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
118500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
118600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
118700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1188aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
118931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
119031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
119131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragInfo != null) {
119231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
119331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.onDropAborted(mDragInfo.cell);
119431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
119531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
119631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
119731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
119831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
119931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12000280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    public boolean isDropEnabled() {
12010280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka        return true;
12020280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka    }
12030280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
12040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
12050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
12060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
12070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
12080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
12090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
12100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
121131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
12127f0f4f3c35fe0b6a94504ec39ac127fa935282efMichael Jurka        if (!mIsSmall) {
12130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
121431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
121531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
121631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12170142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
121831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
12197f0f4f3c35fe0b6a94504ec39ac127fa935282efMichael Jurka        if (!mIsSmall) {
12200142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
122131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
122231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1223138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
122431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1225dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
122631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
122731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
122831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
122931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
123031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
123131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
123231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
123331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
1234aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
123531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
123631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
123731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
123831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
123931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
124031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
124131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
124231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
124331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
124431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
124531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
124631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
124731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
124831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
124931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
125031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
125131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
125231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
125331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
125431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
125531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
125631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
125731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
125831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
125964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
1260dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
12615c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
1262629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
1263574d20ec84551370987dde530c27ec493bdef564Romain Guy
126464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
126564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
126664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
126764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
126864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
126964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
1270dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
127131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1272629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1273629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
1274629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
1275629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
1276629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
1277629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
1278aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1279629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
1280629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1281629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
1282629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
1283aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
12840589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
12850589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
1286629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
1287629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
1288aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
128964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
129064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
129164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
129264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
129364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
129464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
129564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1296629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1297629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
1298629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
12990589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
13000589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
1301629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
1302629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
1303aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1304629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
13050589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
1306629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
1307629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
1308aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
130964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
131064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
131164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
131264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
131373013bf94f49ffbacba2b8300f6a2dd4eeebbd13Brad Fitzpatrick                                            LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
131464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
131564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
131664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
1317629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
1318629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1319aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1320629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
1321629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
1322629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
1323aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
1324aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
1325629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1326629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
1327629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
1328629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
1329629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
1330629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
1331629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1332f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
133364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
133464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
133564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1336aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
133764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
133864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1339629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1340629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
1341629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
1342629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
1343629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
1344e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
134564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
134664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
134764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1348aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
134964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
135064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1351629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1352574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
1353574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1354aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1355629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
1356629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1357629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
1358629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
1359629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
1360629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
1361629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
1362574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1363aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1364629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
1365629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
1366629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
13675c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
136831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
1369629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
137031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
137131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1372f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
137364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
1374dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
1375dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
1376f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1377f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
1378f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
1379f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
1380f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
13810589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
13820589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
1383f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
1384f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
1385f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
1386f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
1387f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
1388f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
138964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
139064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
1391aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
139264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
139364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
139464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
139564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
139664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
139764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
139864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
139964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
1400f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
1401f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
1402f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
1403f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
1404f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
1405f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
140614f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
1407c45b16862918a0c6c253bba12032165b030565afJoe Onorato        if (animate) {
14084cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (mIsSmall) {
14090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                unshrink(mDefaultPage);
14104cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            } else {
14110142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                snapToPage(mDefaultPage);
14124cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
1413c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
14140142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
1415c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
14160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
141731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
141831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14198a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
14208a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
14218a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
14220142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
14230142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
14248a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
14258a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
14260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
14270142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
14280142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
142931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14300142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
14310142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
143231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
143431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
1435