Workspace.java revision 2b9ff37edb3f5965559b3ff7d37e418b4a2917a1
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
19b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.Animator;
20b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.ObjectAnimator;
21af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport com.android.launcher.R;
22495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell
23df7c3a7853abd4dec460247370fe0b17b50866acPatrick Dubroyimport android.animation.PropertyValuesHolder;
24b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haaseimport android.animation.AnimatorSet;
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;
490e26059548e429e5d1c973bebe4c561bead2926fMichael Jurkaimport android.widget.Toast;
5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
51af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.ArrayList;
52af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurkaimport java.util.HashSet;
53edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
5431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * The workspace is a wide area with a wallpaper and a finite number of pages.
560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka * Each page contains a number of icons, folders or widgets the user can
57aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung * interact with. A workspace is meant to be used with a fixed width only.
5831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurkapublic class Workspace extends SmoothPagedView
60dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
61e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    @SuppressWarnings({"UnusedDeclaration"})
623a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato    private static final String TAG = "Launcher.Workspace";
630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
64dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // This is how much the workspace shrinks when we enter all apps or
65dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // customization mode
66dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private static final float SHRINK_FACTOR = 0.16f;
670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private enum ShrinkPosition { SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM };
6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
698f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private final WallpaperManager mWallpaperManager;
70aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private int mDefaultPage;
7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    private boolean mWaitingToShrinkToBottom = false;
7431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
7631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * CellInfo for the cell that is currently being dragged
7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private CellLayout.CellInfo mDragInfo;
79aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
8070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
8170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Target drop area calculated during last acceptDrop call.
8270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
8370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTargetCell = null;
8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
856569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    /**
866569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     * The CellLayout that is currently being dragged over
876569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy     */
886569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    private CellLayout mDragTargetLayout = null;
896569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Launcher mLauncher;
910589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    private IconCache mIconCache;
9200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragController mDragController;
93aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
94aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int[] mTempCell = new int[2];
9670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private int[] mTempEstimate = new int[2];
97a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragCoordinates = new float[2];
98a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    private float[] mTempDragBottomRightCoordinates = new float[2];
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
100d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_X = 4;
101d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    private static final int DEFAULT_CELL_COUNT_Y = 4;
10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1038a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mPreviousIndicator;
1048a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    private Drawable mNextIndicator;
105aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    // State variable that indicated whether the pages are small (ie when you're
107dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // in all apps or customize mode)
108dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    private boolean mIsSmall;
109b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase    private AnimatorListener mUnshrinkAnimationListener;
110dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
111aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs) {
11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        this(context, attrs, 0);
12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
1260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param attrs The attributes set containing the Workspace's customization values.
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param defStyle Unused.
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Workspace(Context context, AttributeSet attrs, int defStyle) {
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs, defStyle);
1310142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mContentIsRefreshable = false;
1320142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mFadeInAdjacentScreens = false;
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1348f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn        mWallpaperManager = WallpaperManager.getInstance(context);
135aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
136aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        TypedArray a = context.obtainStyledAttributes(attrs,
137aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                R.styleable.Workspace, defStyle, 0);
138d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X);
139d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y);
1400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        a.recycle();
14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
143d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY);
1440d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato        setHapticFeedbackEnabled(false);
1450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        initWorkspace();
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Initializes various states for this workspace.
15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
1520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void initWorkspace() {
1530589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Context context = getContext();
1540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mCurrentPage = mDefaultPage;
1550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
1560589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        LauncherApplication app = (LauncherApplication)context.getApplicationContext();
1570589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = app.getIconCache();
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
159b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase        mUnshrinkAnimationListener = new AnimatorListener() {
160b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationStart(Animator animation) {}
161b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationEnd(Animator animation) {
162dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka                mIsSmall = false;
163dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            }
164b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationCancel(Animator animation) {}
165b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            public void onAnimationRepeat(Animator animation) {}
166dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        };
1670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
1680142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mSnapVelocity = 600;
16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index, LayoutParams params) {
17331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
17431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index, params);
17731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child) {
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child);
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int index) {
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
19231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, index);
19331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
19631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, int width, int height) {
19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
19831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
20031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, width, height);
20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
20231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
20331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
20431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void addView(View child, LayoutParams params) {
20531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof CellLayout)) {
20631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.addView(child, params);
20931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
21031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
21231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return The open folder on the current screen, or null if there is none
21331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
21431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    Folder getOpenFolder() {
2150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
2160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int count = currentPage.getChildCount();
21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = 0; i < count; i++) {
2180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            View child = currentPage.getChildAt(i);
219aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            if (child instanceof Folder) {
220aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                Folder folder = (Folder) child;
221aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (folder.getInfo().opened)
222aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    return folder;
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
22631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    ArrayList<Folder> getOpenFolders() {
229dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
230dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        ArrayList<Folder> folders = new ArrayList<Folder>(screenCount);
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
232dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int screen = 0; screen < screenCount; screen++) {
2330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            CellLayout currentPage = (CellLayout) getChildAt(screen);
2340142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int count = currentPage.getChildCount();
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
2360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                View child = currentPage.getChildAt(i);
237aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                if (child instanceof Folder) {
238aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    Folder folder = (Folder) child;
239aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (folder.getInfo().opened)
240aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        folders.add(folder);
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    break;
24231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
24431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return folders;
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2490142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    boolean isDefaultPageShowing() {
2500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return mCurrentPage == mDefaultPage;
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the current screen.
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
2560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka     * @param currentPage
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
2580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
2590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void setCurrentPage(int currentPage) {
2600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.setCurrentPage(currentPage);
2610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        updateWallpaperOffset(mScrollX);
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the current screen. The position and dimension of
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
27131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInCurrentScreen(View child, int x, int y, int spanX, int spanY) {
2750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        addInScreen(child, mCurrentPage, x, y, spanX, spanY, false);
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the current screen. The position and dimension of
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
28231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInCurrentScreen(View child, int x, int y, int spanX, int spanY, boolean insert) {
2900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        addInScreen(child, mCurrentPage, x, y, spanX, spanY, insert);
29131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
29231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
29631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
30131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
30231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY) {
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addInScreen(child, screen, x, y, spanX, spanY, false);
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
308aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    void addInFullScreen(View child, int screen) {
309aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        addInScreen(child, screen, 0, 0, -1, -1);
310aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
311aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Adds the specified child in the specified screen. The position and dimension of
31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * the child are defined by x, y, spanX and spanY.
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param child The child to add in one of the workspace's screens.
31731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param screen The screen in which to add the child.
31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param x The X position of the child in the screen's grid.
31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param y The Y position of the child in the screen's grid.
32031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanX The number of cells spanned horizontally by the child.
32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param spanY The number of cells spanned vertically by the child.
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param insert When true, the child is inserted at the beginning of the children list.
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void addInScreen(View child, int screen, int x, int y, int spanX, int spanY, boolean insert) {
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (screen < 0 || screen >= getChildCount()) {
326291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
327291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler                + " (was " + screen + "); skipping child");
328291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandler            return;
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
33131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout group = (CellLayout) getChildAt(screen);
33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (lp == null) {
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp = new CellLayout.LayoutParams(x, y, spanX, spanY);
33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellX = x;
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellY = y;
33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellHSpan = spanX;
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            lp.cellVSpan = spanY;
34031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
341aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
3426569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // Get the canonical child id to uniquely represent this view in this screen
343d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen        int childId = LauncherModel.getCellLayoutChildId(child.getId(), screen, x, y, spanX, spanY);
344aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (!group.addViewToCellLayout(child, insert ? 0 : -1, childId, lp)) {
345aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // TODO: This branch occurs when the workspace is adding views
346aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // outside of the defined grid
3476569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            // maybe we should be deleting these items from the LauncherModel?
348aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            Log.w(TAG, "Failed to add to item at (" + lp.cellX + "," + lp.cellY + ") to CellLayout");
349aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
350aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!(child instanceof Folder)) {
3520d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato            child.setHapticFeedbackEnabled(false);
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            child.setOnLongClickListener(mLongClickListener);
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
35500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (child instanceof DropTarget) {
356aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            mDragController.addDropTarget((DropTarget) child);
35700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
35931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
360a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    CellLayout.CellInfo updateOccupiedCellsForCurrentScreen(boolean[] occupied) {
3610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout group = (CellLayout) getChildAt(mCurrentPage);
36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (group != null) {
363c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka            return group.updateOccupiedCells(occupied, null);
36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
368dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    public boolean onTouch(View v, MotionEvent event) {
369dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // this is an intercepted event being forwarded from a cell layout
370dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        if (mIsSmall) {
3712b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            mLauncher.onWorkspaceClick((CellLayout) v);
37296226223d9849842bb2a67af051acbae9e0677d5Michael Jurka            return true;
373dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
374dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        return false;
3750e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka    }
3760e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka
3770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void pageBeginMoving() {
3780142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mNextPage != INVALID_PAGE) {
3790142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // we're snapping to a particular screen
3800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            enableChildrenCache(mCurrentPage, mNextPage);
3810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
3820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // this is when user is actively dragging a particular screen, they might
3830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // swipe it either left or right (but we won't advance by more than one screen)
3840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void pageEndMoving() {
3890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        clearChildrenCache();
3900142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
3910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
3920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
3930142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void notifyPageSwitchListener() {
3940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.notifyPageSwitchListener();
3950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
3960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mPreviousIndicator != null) {
3970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // if we know the next page, we show the indication for it right away; it looks
3980142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // weird if the indicators are lagging
3990142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int page = mNextPage;
4000142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (page == INVALID_PAGE) {
4010142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                page = mCurrentPage;
4020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4030142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mPreviousIndicator.setLevel(page);
4040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            mNextIndicator.setLevel(page);
4050142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        }
4060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
4070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    };
4080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4098f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    private void updateWallpaperOffset() {
410798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy        updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft));
411798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    }
412798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy
413798300c4c05b12228f2e4f31c49c3cb728a37889Romain Guy    private void updateWallpaperOffset(int scrollRange) {
41486f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        final boolean isStaticWallpaper = (mWallpaperManager != null) &&
41586f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                (mWallpaperManager.getWallpaperInfo() == null);
41686f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung        if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
41786f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            IBinder token = getWindowToken();
41886f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            if (token != null) {
41986f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
42086f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
42186f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung                        Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
42286f7753bbd6d87ce85195b0715e5548edbfdb7d1Winson Chung            }
423956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        }
4248f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn    }
425aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
42600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    protected void onAttachedToWindow() {
42700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        super.onAttachedToWindow();
428956091ba7863bd72086275e61084864994dd6fa7Joe Onorato        computeScroll();
42900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.setWindowToken(getWindowToken());
43000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
43100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
43231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
43331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
4340142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onLayout(changed, left, top, right, bottom);
435aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
43679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // if shrinkToBottom() is called on initialization, it has to be deferred
43779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        // until after the first call to onLayout so that it has the correct width
43879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mWaitingToShrinkToBottom) {
43979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            shrinkToBottom(false);
44079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = false;
44179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
44279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
443aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (LauncherApplication.isInPlaceRotationEnabled()) {
444aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // When the device is rotated, the scroll position of the current screen
445aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            // needs to be refreshed
4460142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(getCurrentPage());
447aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        }
44831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
44931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
45031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
4510142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void dispatchDraw(Canvas canvas) {
4520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (mIsSmall) {
4530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            // Draw all the workspaces if we're small
4540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int pageCount = getChildCount();
4550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final long drawingTime = getDrawingTime();
4560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            for (int i = 0; i < pageCount; i++) {
4570142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                final View page = (View) getChildAt(i);
4580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
4590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                if (page.getAlpha() != 1.0f) {
4600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                    page.setAlpha(1.0f);
4610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                }
4620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                drawChild(canvas, page, drawingTime);
4630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            }
4640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else {
4650142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.dispatchDraw(canvas);
46631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
46731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
46831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
46931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
47031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
471678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
47231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
47331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (openFolder != null) {
47431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return openFolder.requestFocus(direction, previouslyFocusedRect);
47531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
4760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                return super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
47731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
47831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
47931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
48031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
48131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
48231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
483c2e24c0a37ddeab930f731c062705d435e477f75Romain Guy    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
484678862186af4ea70d9b4012c9bc127e7fea5e607Joe Onorato        if (!mLauncher.isAllAppsVisible()) {
48531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Folder openFolder = getOpenFolder();
4860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            if (openFolder != null) {
48731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                openFolder.addFocusables(views, direction);
4880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            } else {
4890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                super.addFocusables(views, direction, focusableMode);
49031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
49131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
49231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
49331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
49431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
4957bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    public boolean dispatchTouchEvent(MotionEvent ev) {
4967bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
49754dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps
49854dd75463d0eb47c2f468e19063bdc4141dfdf74Michael Jurka            // ie when you click on a mini-screen, it zooms back to that screen)
4996b4adbc0558fcebbd44998bd00dcd334ddbee32dJoe Onorato            if (!LauncherApplication.isScreenXLarge() && mLauncher.isAllAppsVisible()) {
5007bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato                return false;
5017bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato            }
5027bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        }
5037bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato        return super.dispatchTouchEvent(ev);
5047bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato    }
5057bb1749c69384faf00b238f0684d3b2e23406451Joe Onorato
5060142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    void enableChildrenCache(int fromPage, int toPage) {
5070142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (fromPage > toPage) {
5080142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            final int temp = fromPage;
5090142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            fromPage = toPage;
5100142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            toPage = temp;
5113a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron        }
512aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
513dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
514fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
5150142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        fromPage = Math.max(fromPage, 0);
5160142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        toPage = Math.min(toPage, screenCount - 1);
517fea5d0250767ab938f623a404e6292a32dd2fdf5Adam Powell
5180142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        for (int i = fromPage; i <= toPage; i++) {
51931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
52031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(true);
52131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawingCacheEnabled(true);
52231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
52331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
52431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
52531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void clearChildrenCache() {
526dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
527dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
52831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
52931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            layout.setChildrenDrawnWithCacheEnabled(false);
53031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
53131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
53231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
53331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
53431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
5352bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato        if (mLauncher.isAllAppsVisible()) {
5362bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            // Cancel any scrolling that is in progress.
5372bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            if (!mScroller.isFinished()) {
5382bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato                mScroller.abortAnimation();
5392bc6b7c2b8b651dde0a65c64c127f5b85c1290d2Joe Onorato            }
5400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            snapToPage(mCurrentPage);
5417c312c15e33b6cffbda707429e88ade498fc9f5eJoe Onorato            return false; // We don't want the events.  Let them fall through to the all apps view.
54231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
54331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5440142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        return super.onTouchEvent(ev);
54531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
546aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
54701f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    public boolean isSmall() {
54801f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka        return mIsSmall;
54901f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
55001f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
5516b509c1fd62a39916bb957eac07917161f549206Patrick Dubroy    void shrinkToTop(boolean animated) {
5520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_TOP, animated);
55301f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    }
55401f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka
55501f0ed4126be412c8c4352026dad3b2a49832267Michael Jurka    void shrinkToMiddle() {
5560142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true);
557213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
558213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
559213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    void shrinkToBottom() {
56079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        shrinkToBottom(true);
56179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    }
56279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka
56379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka    void shrinkToBottom(boolean animated) {
56479212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        if (mFirstLayout) {
56579212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // (mFirstLayout == "first layout has not happened yet")
56679212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // if we get a call to shrink() as part of our initialization (for example, if
56779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // Launcher is started in All Apps mode) then we need to wait for a layout call
56879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            // to get our width so we can layout the mini-screen views correctly
56979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            mWaitingToShrinkToBottom = true;
57079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        } else {
5710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            shrink(ShrinkPosition.SHRINK_TO_BOTTOM, animated);
57279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka        }
573213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka    }
574213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
575dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // we use this to shrink the workspace for the all apps view and the customize view
5760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void shrink(ShrinkPosition shrinkPosition, boolean animated) {
577dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        mIsSmall = true;
5787247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final Resources res = getResources();
579dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenWidth = getWidth();
580213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        final int screenHeight = getHeight();
5810142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5820142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        // Making the assumption that all pages have the same width as the 0th
5830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageWidth = getChildAt(0).getMeasuredWidth();
5840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int pageHeight = getChildAt(0).getMeasuredHeight();
5850142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
5860142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth);
5870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight);
5887247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy        final float scaledSpacing = res.getDimension(R.dimen.smallScreenSpacing);
589dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
590dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
5910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * scaledSpacing;
592213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka
593213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        float newY = getResources().getDimension(R.dimen.smallScreenVerticalMargin);
5940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM) {
5950142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight - newY - scaledPageHeight;
5960142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) {
5970142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newY = screenHeight / 2 - scaledPageHeight / 2;
598213d96354e7407dba5c9715eb10d04bebd82c395Michael Jurka        }
599dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
600dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // We animate all the screens to the centered position in workspace
601dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // At the same time, the screens become greyed/dimmed
602dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
603dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        // newX is initialized to the left-most position of the centered screens
6040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2;
605dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
606dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            CellLayout cl = (CellLayout) getChildAt(i);
607a67e867db9d639ed2afcc97e9d04a67fc46f2669Patrick Dubroy            cl.setPivotX(0.0f);
608a67e867db9d639ed2afcc97e9d04a67fc46f2669Patrick Dubroy            cl.setPivotY(0.0f);
60979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            if (animated) {
6107247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
611b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                new ObjectAnimator(duration, cl,
612df7c3a7853abd4dec460247370fe0b17b50866acPatrick Dubroy                        new PropertyValuesHolder("x", newX),
613df7c3a7853abd4dec460247370fe0b17b50866acPatrick Dubroy                        new PropertyValuesHolder("y", newY),
614df7c3a7853abd4dec460247370fe0b17b50866acPatrick Dubroy                        new PropertyValuesHolder("scaleX", SHRINK_FACTOR),
615df7c3a7853abd4dec460247370fe0b17b50866acPatrick Dubroy                        new PropertyValuesHolder("scaleY", SHRINK_FACTOR),
616df7c3a7853abd4dec460247370fe0b17b50866acPatrick Dubroy                        new PropertyValuesHolder("dimmedBitmapAlpha", 1.0f)).start();
61779212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            } else {
61879212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setX((int)newX);
61979212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setY((int)newY);
62079212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setScaleX(SHRINK_FACTOR);
62179212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setScaleY(SHRINK_FACTOR);
62279212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka                cl.setDimmedBitmapAlpha(1.0f);
62379212d81361d1ad8c941c48f8323eb526643ca68Michael Jurka            }
624dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            // increment newX for the next screen
6250142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            newX += scaledPageWidth + scaledSpacing;
626dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka            cl.setOnInterceptTouchListener(this);
627dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
628dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        setChildrenDrawnWithCacheEnabled(true);
629dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
630dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
631dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    // We call this when we trigger an unshrink by clicking on the CellLayout cl
6322b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public void unshrink(CellLayout clThatWasClicked) {
6330142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int newCurrentPage = mCurrentPage;
6344cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        final int screenCount = getChildCount();
6354cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        for (int i = 0; i < screenCount; i++) {
6364cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (getChildAt(i) == clThatWasClicked) {
6370142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                newCurrentPage = i;
6384cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
6394cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        }
6400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        unshrink(newCurrentPage);
6414cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
6424cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
6430142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private void unshrink(int newCurrentPage) {
644b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
6450142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            int delta = (newCurrentPage - mCurrentPage)*getWidth();
6464cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
647b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
648b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
649b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                CellLayout cl = (CellLayout) getChildAt(i);
650b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka                cl.setX(cl.getX() + delta);
651b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
6520142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            snapToPage(newCurrentPage);
653b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            unshrink();
6540142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
6550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(newCurrentPage);
656b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        }
657dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
658dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
6594cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink() {
6604cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka        unshrink(true);
6614cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    }
6624cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
6634cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka    void unshrink(boolean animated) {
664b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka        if (mIsSmall) {
665b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase            AnimatorSet s = new AnimatorSet();
666b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            final int screenCount = getChildCount();
6674cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka
6684cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            final int duration = getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
669b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            for (int i = 0; i < screenCount; i++) {
6707247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy                final CellLayout cl = (CellLayout)getChildAt(i);
671a67e867db9d639ed2afcc97e9d04a67fc46f2669Patrick Dubroy                cl.setPivotX(0.0f);
672a67e867db9d639ed2afcc97e9d04a67fc46f2669Patrick Dubroy                cl.setPivotY(0.0f);
6734cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                if (animated) {
6744cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    s.playTogether(
675b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "translationX", 0.0f),
676b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "translationY", 0.0f),
677b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "scaleX", 1.0f),
678b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "scaleY", 1.0f),
679b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase                            new ObjectAnimator<Float>(duration, cl, "dimmedBitmapAlpha", 0.0f));
6804cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                } else {
6814cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationX(0.0f);
6824cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setTranslationY(0.0f);
6834cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleX(1.0f);
6844cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setScaleY(1.0f);
6854cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                    cl.setDimmedBitmapAlpha(0.0f);
6864cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka                }
687b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            }
688b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            s.addListener(mUnshrinkAnimationListener);
689b0f28bd9a52fa4e343c8299d1c3e225d8e01c1e9Michael Jurka            s.start();
690dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        }
691dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    }
692dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka
69331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void startDrag(CellLayout.CellInfo cellInfo) {
69431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        View child = cellInfo.cell;
695aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
69631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Make sure the drag was started by a long press as opposed to a long click.
6977984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert        if (!child.isInTouchMode()) {
69831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return;
69931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
700aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
70131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = cellInfo;
7020142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        mDragInfo.screen = mCurrentPage;
703aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
7040142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        CellLayout current = ((CellLayout) getChildAt(mCurrentPage));
70531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
70631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        current.onDragChild(child);
70700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
70831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        invalidate();
70931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
71031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7110589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) {
71231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        addApplicationShortcut(info, cellInfo, false);
71331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
71431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7150589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo,
71631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean insertAtFirst) {
71731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout layout = (CellLayout) getChildAt(cellInfo.screen);
71831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int[] result = new int[2];
71931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
72031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        layout.cellToPoint(cellInfo.cellX, cellInfo.cellY, result);
72131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(result[0], result[1], info, layout, insertAtFirst);
72231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
72331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
72400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
72500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            DragView dragView, Object dragInfo) {
726a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout cellLayout = getCurrentDropLayout();
727a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originX = x - xOffset;
728a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originY = y - yOffset;
729a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (mIsSmall) {
730a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // find out which target layout is over
731a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            final float[] localXY = mTempDragCoordinates;
732a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            localXY[0] = originX;
733a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            localXY[1] = originY;
734a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            final float[] localBottomRightXY = mTempDragBottomRightCoordinates;
735a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // we need to subtract left/top here because DragController already adds
736a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // dragRegionLeft/Top to xOffset and yOffset
737a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            localBottomRightXY[0] = originX + dragView.getDragRegionWidth();
738a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            localBottomRightXY[1] = originY + dragView.getDragRegionHeight();
7390142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            cellLayout =  findMatchingPageForDragOver(localXY, localBottomRightXY);
740a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (cellLayout == null) {
741a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                // cancel the drag if we're not over a mini-screen at time of drop
742a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                // TODO: maybe add a nice fade here?
743a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                return;
744a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
745a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // localXY will be transformed into the local screen's coordinate space; save that info
746a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            originX = (int)localXY[0];
747a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            originY = (int)localXY[1];
748a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
74931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (source != this) {
750a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            onDropExternal(originX, originY, dragInfo, cellLayout);
75131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
75231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Move internally
75331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragInfo != null) {
75431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final View cell = mDragInfo.cell;
7550142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
75652d9cb32608e7c3d065b4fb8e97269e238f1683eRomain Guy                if (index != mDragInfo.screen) {
75731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
75831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    originalCellLayout.removeView(cell);
759aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    addInScreen(cell, index, mDragInfo.cellX, mDragInfo.cellY,
760aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                            mDragInfo.spanX, mDragInfo.spanY);
76131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
762a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
763a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                mTargetCell = estimateDropCell(originX, originY,
764aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        mDragInfo.spanX, mDragInfo.spanY, cell, cellLayout,
765aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        mTargetCell);
766aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                cellLayout.onDropChild(cell);
76731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
768aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // update the item's position after drop
76984f296c106cb1c7b6d3ae6c6d5508a17f1324e29Romain Guy                final ItemInfo info = (ItemInfo) cell.getTag();
770aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell
771aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        .getLayoutParams();
772aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                lp.cellX = mTargetCell[0];
773aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                lp.cellY = mTargetCell[1];
774aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
77531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                LauncherModel.moveItemInDatabase(mLauncher, info,
776aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        LauncherSettings.Favorites.CONTAINER_DESKTOP, index,
777aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        lp.cellX, lp.cellY);
77831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
77931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
78031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
78131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
782aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragEnter(DragSource source, int x, int y, int xOffset,
783aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
78431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
78531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
786440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public DropTarget getDropTargetDelegate(DragSource source, int x, int y, int xOffset, int yOffset,
7876569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            DragView dragView, Object dragInfo) {
7886569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
789440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // We may need to delegate the drag to a child view. If a 1x1 item
790440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // would land in a cell occupied by a DragTarget (e.g. a Folder),
791440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // then drag events should be handled by that child.
792440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
7936569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        ItemInfo item = (ItemInfo)dragInfo;
794440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        CellLayout currentLayout = getCurrentDropLayout();
795440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
796440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        int dragPointX, dragPointY;
797440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (item.spanX == 1 && item.spanY == 1) {
798440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // For a 1x1, calculate the drop cell exactly as in onDragOver
799440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x - xOffset;
800440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y - yOffset;
801440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        } else {
802440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Otherwise, use the exact drag coordinates
803440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointX = x;
804440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            dragPointY = y;
805440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
806440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
807440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // If we are dragging over a cell that contains a DropTarget that will
808440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        // accept the drop, delegate to that DropTarget.
809440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        final int[] cellXY = mTempCell;
810440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        currentLayout.estimateDropCell(dragPointX, dragPointY, item.spanX, item.spanY, cellXY);
811440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        View child = currentLayout.getChildAt(cellXY[0], cellXY[1]);
812440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        if (child instanceof DropTarget) {
813440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = (DropTarget)child;
814440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            if (target.acceptDrop(source, x, y, xOffset, yOffset, dragView, dragInfo)) {
815440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                return target;
816440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            }
817440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        }
818440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy        return null;
819440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    }
8206569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
821a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // xy = upper left corner of item being dragged
822a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // bottomRightXy = lower right corner of item being dragged
823a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // This method will see which mini-screen is most overlapped by the item being dragged, and
824a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // return it. It will also transform the parameters xy and bottomRightXy into the local
825a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    // coordinate space of the returned screen
8260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    private CellLayout findMatchingPageForDragOver(float[] xy, float[] bottomRightXy) {
827a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float x = xy[0];
828a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float y = xy[1];
829a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float right = bottomRightXy[0];
830a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float bottom = bottomRightXy[1];
831a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
832a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float bestX = 0;
833a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float bestY = 0;
834a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float bestRight = 0;
835a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float bestBottom = 0;
836a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
837a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        Matrix inverseMatrix = new Matrix();
838a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
839a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        // We loop through all the screens (ie CellLayouts) and see which one overlaps the most
840a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        // with the item being dragged.
841a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int screenCount = getChildCount();
842a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout bestMatchingScreen = null;
843a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        float bestOverlapSoFar = 0;
844a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        for (int i = 0; i < screenCount; i++) {
845a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            CellLayout cl = (CellLayout)getChildAt(i);
846a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // Transform the coordinates of the item being dragged to the CellLayout's coordinates
847a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float left = cl.getLeft();
848a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float top = cl.getTop();
849a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            xy[0] = x + mScrollX - left;
850a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            xy[1] = y + mScrollY - top;
851a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            cl.getMatrix().invert(inverseMatrix);
852a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
853a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            bottomRightXy[0] = right + mScrollX - left;
854a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            bottomRightXy[1] = bottom + mScrollY - top;
855a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
856a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            inverseMatrix.mapPoints(xy);
857a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            inverseMatrix.mapPoints(bottomRightXy);
858a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
859a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float dragRegionX = xy[0];
860a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float dragRegionY = xy[1];
861a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float dragRegionRight = bottomRightXy[0];
862a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float dragRegionBottom = bottomRightXy[1];
863a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
864a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // Find the overlapping region
865a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float overlapLeft = Math.max(0f, dragRegionX);
866a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float overlapTop = Math.max(0f, dragRegionY);
867a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float overlapBottom = Math.min(cl.getHeight(), dragRegionBottom);
868a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            float overlapRight = Math.min(cl.getWidth(), dragRegionRight);
869a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
870a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (overlapRight >= 0 && overlapLeft <= cl.getWidth() &&
871a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    overlapTop >= 0 && overlapBottom <= cl.getHeight()) {
872a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                // Calculate the size of the overlapping region
873a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                float overlap = (overlapRight - overlapLeft) * (overlapBottom - overlapTop);
874a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                if (overlap > bestOverlapSoFar) {
875a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestOverlapSoFar = overlap;
876a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestMatchingScreen = cl;
877a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestX = xy[0];
878a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestY = xy[1];
879a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestRight = bottomRightXy[0];
880a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    bestBottom = bottomRightXy[1];
881a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
882a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka             }
883a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
884a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (bestMatchingScreen != null && bestMatchingScreen != mDragTargetLayout) {
885a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (mDragTargetLayout != null) {
886a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                mDragTargetLayout.onDragComplete();
887a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
888a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            mDragTargetLayout = bestMatchingScreen;
889a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
890a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        xy[0] = bestX;
891a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        xy[1] = bestY;
892a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        bottomRightXy[0] = bestRight;
893a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        bottomRightXy[1] = bestBottom;
894a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        return bestMatchingScreen;
895a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
896a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
897440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy    public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset,
898440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DragView dragView, Object dragInfo) {
899440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
900976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        final ItemInfo item = (ItemInfo)dragInfo;
901a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        CellLayout currentLayout = getCurrentDropLayout();
9026569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
9036569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (dragInfo instanceof LauncherAppWidgetInfo) {
9046569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo)dragInfo;
9056569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
9066569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            if (widgetInfo.spanX == -1) {
9076569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                // Calculate the grid spans needed to fit this widget
9088f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy                int[] spans = currentLayout.rectToCell(widgetInfo.minWidth, widgetInfo.minHeight, null);
9096569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                item.spanX = spans[0];
9106569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                item.spanY = spans[1];
9116569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            }
9126569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
913a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originX = x - xOffset;
914a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        int originY = y - yOffset;
915a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (mIsSmall) {
916a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // find out which mini screen the dragged item is over
917a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            final float[] localXY = mTempDragCoordinates;
918a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            localXY[0] = originX;
919a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            localXY[1] = originY;
920a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            final float[] localBottomRightXY = mTempDragBottomRightCoordinates;
921a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
922a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            localBottomRightXY[0] = originX + dragView.getDragRegionWidth();
923a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            localBottomRightXY[1] = originY + dragView.getDragRegionHeight();
9240142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            currentLayout = findMatchingPageForDragOver(localXY, localBottomRightXY);
925a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (currentLayout != null) {
926a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                currentLayout.setHover(true);
927a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
928a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
929a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            originX = (int)localXY[0];
930a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            originY = (int)localXY[1];
931a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
932a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
933a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (source != this) {
934a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // This is a hack to fix the point used to determine which cell an icon from the all
935a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            // apps screen is over
936a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            if (item != null && item.spanX == 1 && currentLayout != null) {
937a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                int dragRegionLeft = (dragView.getWidth() - currentLayout.getCellWidth()) / 2;
938a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
939a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                originX += dragRegionLeft - dragView.getDragRegionLeft();
940a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                if (dragView.getDragRegionWidth() != currentLayout.getCellWidth()) {
941a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    dragView.setDragRegion(dragView.getDragRegionLeft(), dragView.getDragRegionTop(),
942a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                            currentLayout.getCellWidth(), dragView.getDragRegionHeight());
943a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                }
944a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            }
945a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
9466569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (currentLayout != mDragTargetLayout) {
9476569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            if (mDragTargetLayout != null) {
9486569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy                mDragTargetLayout.onDragComplete();
9496569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            }
9506569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            mDragTargetLayout = currentLayout;
9516569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
9526569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
953a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        // only visualize the drop locations for moving icons within the home screen on tablet
954a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        // on phone, we also visualize icons dragged in from All Apps
955a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if ((!LauncherApplication.isScreenXLarge() || source == this)
956a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                && mDragTargetLayout != null) {
957a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            final View child = (mDragInfo == null) ? null : mDragInfo.cell;
958a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            mDragTargetLayout.visualizeDropLocation(
959a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    child, originX, originY, item.spanX, item.spanY);
960976ebec9e31643d3513f9f0de2b433d9aa186ce9Patrick Dubroy        }
96131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
96231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
963aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    public void onDragExit(DragSource source, int x, int y, int xOffset,
964aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            int yOffset, DragView dragView, Object dragInfo) {
9656569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (mDragTargetLayout != null) {
9666569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            mDragTargetLayout.onDragComplete();
9676569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            mDragTargetLayout = null;
9686569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        }
96931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
97031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
971aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
972aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout) {
97331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        onDropExternal(x, y, dragInfo, cellLayout, false);
97431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
975aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
9762b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    /**
9772b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * Add the item specified by dragInfo to the given layout.
9782b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * This is basically the equivalent of onDropExternal, except it's not initiated
9792b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * by drag and drop.
9802b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     * @return true if successful
9812b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy     */
9822b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    public boolean addExternalItemToScreen(Object dragInfo, View layout) {
9832b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        CellLayout cl = (CellLayout) layout;
9842b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        ItemInfo info = (ItemInfo) dragInfo;
9852b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
9862b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        final CellLayout.CellInfo cellInfo = cl.updateOccupiedCells(null, null);
9872b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        if (cellInfo.findCellForSpan(mTempEstimate, info.spanX, info.spanY)) {
9882b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            onDropExternal(0, 0, dragInfo, cl, false);
9892b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy            return true;
9902b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        }
9912b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy        return false;
9922b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy    }
9932b9ff37edb3f5965559b3ff7d37e418b4a2917a1Patrick Dubroy
994aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    private void onDropExternal(int x, int y, Object dragInfo,
995aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            CellLayout cellLayout, boolean insertAtFirst) {
99631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Drag from somewhere else
99731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ItemInfo info = (ItemInfo) dragInfo;
99831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
999af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        View view = null;
100031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
100131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (info.itemType) {
100231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
100331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1004e48e7c1a62e6a367803dca62c8fce9de57121b0fJoe Onorato            if (info.container == NO_ID && info instanceof ApplicationInfo) {
100531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Came from all apps -- make a copy
1006aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                info = new ShortcutInfo((ApplicationInfo) info);
100731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
1008aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            view = mLauncher.createShortcut(R.layout.application, cellLayout,
1009aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    (ShortcutInfo) info);
101031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
101131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
101231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher,
10130142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                    (ViewGroup) getChildAt(mCurrentPage),
1014aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    ((UserFolderInfo) info));
101531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
1016af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
1017af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            cellLayout.setTagToCellInfoForPoint(x, y);
1018a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            int[] position = new int[2];
1019a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            position[0] = x;
1020a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            position[1] = y;
1021a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            mLauncher.addAppWidgetFromDrop(((LauncherAppWidgetInfo)dragInfo).providerName,
1022a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka                    cellLayout.getTag(), position);
1023af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            break;
102431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        default:
1025aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            throw new IllegalStateException("Unknown item type: "
1026aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    + info.itemType);
102731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
102831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10296569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        // If the view is null, it has already been added.
10306569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        if (view == null) {
10316569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            cellLayout.onDragComplete();
10326569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        } else {
10336569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            mTargetCell = estimateDropCell(x, y, 1, 1, view, cellLayout, mTargetCell);
1034aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            addInScreen(view, indexOfChild(cellLayout), mTargetCell[0],
1035aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    mTargetCell[1], info.spanX, info.spanY, insertAtFirst);
1036aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung            cellLayout.onDropChild(view);
10376569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
103831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1039af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka            LauncherModel.addOrMoveItemInDatabase(mLauncher, info,
10400142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                    LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage,
1041aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    lp.cellX, lp.cellY);
1042af44209bfa60da3c7ab49b7f508f9effd316ee41Michael Jurka        }
104331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1044aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
104570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
104670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Return the current {@link CellLayout}, correctly picking the destination
104770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * screen while a scroll is in progress.
104870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
104970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    private CellLayout getCurrentDropLayout() {
10500142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        int index = mScroller.isFinished() ? mCurrentPage : mNextPage;
105170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return (CellLayout) getChildAt(index);
105270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
105331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
105470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
105570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * {@inheritDoc}
105670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
105770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    public boolean acceptDrop(DragSource source, int x, int y,
105800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            int xOffset, int yOffset, DragView dragView, Object dragInfo) {
10594c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy        final CellLayout layout = getCurrentDropLayout();
1060c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final CellLayout.CellInfo dragCellInfo = mDragInfo;
1061c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
1062c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
10634c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1064c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
1065c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final CellLayout.CellInfo cellInfo = layout.updateOccupiedCells(null, ignoreView);
10664c58c485d8c02f8ca7e8b4d93140440f6a3a5131Romain Guy
1067c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        if (cellInfo.findCellForSpan(mTempEstimate, spanX, spanY)) {
10680e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return true;
10690e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        } else {
10700e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            Toast.makeText(getContext(), getContext().getString(R.string.out_of_space), Toast.LENGTH_SHORT).show();
10710e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka            return false;
10720e26059548e429e5d1c973bebe4c561bead2926fMichael Jurka        }
107370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1074aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
107570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
107670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * {@inheritDoc}
107770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
107870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    public Rect estimateDropLocation(DragSource source, int x, int y,
107900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle) {
108070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        final CellLayout layout = getCurrentDropLayout();
1081aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
108231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final CellLayout.CellInfo cellInfo = mDragInfo;
108370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        final int spanX = cellInfo == null ? 1 : cellInfo.spanX;
108470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        final int spanY = cellInfo == null ? 1 : cellInfo.spanY;
108570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        final View ignoreView = cellInfo == null ? null : cellInfo.cell;
1086aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
108770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        final Rect location = recycle != null ? recycle : new Rect();
1088aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
108970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find drop cell and convert into rectangle
1090aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        int[] dropCell = estimateDropCell(x - xOffset, y - yOffset, spanX,
1091aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                spanY, ignoreView, layout, mTempCell);
1092aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
109370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        if (dropCell == null) {
109470864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            return null;
109570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        }
1096aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
109770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        layout.cellToPoint(dropCell[0], dropCell[1], mTempEstimate);
109870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        location.left = mTempEstimate[0];
109970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        location.top = mTempEstimate[1];
1100aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
110170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        layout.cellToPoint(dropCell[0] + spanX, dropCell[1] + spanY, mTempEstimate);
110270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        location.right = mTempEstimate[0];
110370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        location.bottom = mTempEstimate[1];
1104aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
110570864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        return location;
110631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
110731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
110870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    /**
110970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     * Calculate the nearest cell where the given object would be dropped.
111070864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey     */
1111263e019baafb3b6cbcfdef9c81d74a4bea769180Romain Guy    private int[] estimateDropCell(int pixelX, int pixelY,
111270864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey            int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
11136569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
11146569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        final int[] cellXY = mTempCell;
11156569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        layout.estimateDropCell(pixelX, pixelY, spanX, spanY, cellXY);
11166569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy        layout.cellToPoint(cellXY[0], cellXY[1], mTempEstimate);
11176569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1118c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        final CellLayout.CellInfo cellInfo = layout.updateOccupiedCells(null, ignoreView);
111970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        // Find the best target drop location
1120c28de51eedb26848abf9245ddd19e021d30be318Michael Jurka        return layout.findNearestVacantArea(mTempEstimate[0], mTempEstimate[1], spanX, spanY, cellInfo, recycle);
112170864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey    }
1122aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
11238f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    /**
11248f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     * Estimate the size that a child with the given dimensions will take in the current screen.
11258f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy     */
11268f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    void estimateChildSize(int minWidth, int minHeight, int[] result) {
11270142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result);
11288f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy    }
11298f86ddcb90063a56c25c9c782316574bc4e5dd93Patrick Dubroy
113031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setLauncher(Launcher launcher) {
113131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mLauncher = launcher;
113231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
113331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
113400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
113500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
113631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
113731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
113831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onDropCompleted(View target, boolean success) {
1139aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung        if (success) {
114031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (target != this && mDragInfo != null) {
114131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
114231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.removeView(mDragInfo.cell);
114300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragInfo.cell instanceof DropTarget) {
114400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragController.removeDropTarget((DropTarget)mDragInfo.cell);
114500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
1146aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                // final Object tag = mDragInfo.cell.getTag();
114731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
114831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        } else {
114931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragInfo != null) {
115031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
115131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                cellLayout.onDropAborted(mDragInfo.cell);
115231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
115331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
115431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
115531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = null;
115631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
115731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11580142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
11590142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    protected void onRestoreInstanceState(Parcelable state) {
11600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        super.onRestoreInstanceState(state);
11610142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        Launcher.setScreen(mCurrentPage);
11620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
11630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
11640142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
116531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollLeft() {
11667f0f4f3c35fe0b6a94504ec39ac127fa935282efMichael Jurka        if (!mIsSmall) {
11670142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollLeft();
116831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
116931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
117031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11710142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
117231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void scrollRight() {
11737f0f4f3c35fe0b6a94504ec39ac127fa935282efMichael Jurka        if (!mIsSmall) {
11740142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            super.scrollRight();
117531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
117631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1177138a04170d964da9cdec228e95b976875ae52481Karl Rosaen
117831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder getFolderForTag(Object tag) {
1179dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
118031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
118131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
118231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
118331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
118431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
118531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
118631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (lp.cellHSpan == 4 && lp.cellVSpan == 4 && child instanceof Folder) {
118731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    Folder f = (Folder) child;
1188aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                    if (f.getInfo() == tag && f.getInfo().opened) {
118931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return f;
119031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
119131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
119231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
119331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
119431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
119531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
119631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
119731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public View getViewForTag(Object tag) {
119831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int screenCount = getChildCount();
119931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int screen = 0; screen < screenCount; screen++) {
120031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            CellLayout currentScreen = ((CellLayout) getChildAt(screen));
120131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int count = currentScreen.getChildCount();
120231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            for (int i = 0; i < count; i++) {
120331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                View child = currentScreen.getChildAt(i);
120431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (child.getTag() == tag) {
120531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    return child;
120631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
120731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
120831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
120931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
121031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
121131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
121231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
121364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void removeItems(final ArrayList<ApplicationInfo> apps) {
1214dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
12155c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy        final PackageManager manager = getContext().getPackageManager();
1216629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy        final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
1217574d20ec84551370987dde530c27ec493bdef564Romain Guy
121864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final HashSet<String> packageNames = new HashSet<String>();
121964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        final int appCount = apps.size();
122064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        for (int i = 0; i < appCount; i++) {
122164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato            packageNames.add(apps.get(i).componentName.getPackageName());
122264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato        }
122364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato
1224dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
122531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1226629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1227629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            // Avoid ANRs by treating each screen separately
1228629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            post(new Runnable() {
1229629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                public void run() {
1230629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    final ArrayList<View> childrenToRemove = new ArrayList<View>();
1231629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childrenToRemove.clear();
1232aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1233629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    int childCount = layout.getChildCount();
1234629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1235629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        final View view = layout.getChildAt(j);
1236629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        Object tag = view.getTag();
1237aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
12380589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                        if (tag instanceof ShortcutInfo) {
12390589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ShortcutInfo info = (ShortcutInfo) tag;
1240629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Intent intent = info.intent;
1241629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ComponentName name = intent.getComponent();
1242aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
124364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
124464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
124564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(name.getPackageName())) {
124664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        // TODO: This should probably be done on a worker thread
124764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
124864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        childrenToRemove.add(view);
124964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
125064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1251629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1252629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof UserFolderInfo) {
1253629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final UserFolderInfo info = (UserFolderInfo) tag;
12540589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> contents = info.contents;
12550589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                            final ArrayList<ShortcutInfo> toRemove = new ArrayList<ShortcutInfo>(1);
1256629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final int contentsCount = contents.size();
1257629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            boolean removedFromFolder = false;
1258aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1259629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            for (int k = 0; k < contentsCount; k++) {
12600589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                                final ShortcutInfo appInfo = contents.get(k);
1261629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Intent intent = appInfo.intent;
1262629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final ComponentName name = intent.getComponent();
1263aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
126464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
126564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    for (String packageName: packageNames) {
126664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        if (packageName.equals(name.getPackageName())) {
126764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            toRemove.add(appInfo);
126864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            // TODO: This should probably be done on a worker thread
126964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            LauncherModel.deleteItemFromDatabase(
127064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                                    mLauncher, appInfo);
127164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                            removedFromFolder = true;
127264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        }
127364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
1274629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                }
1275629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1276aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1277629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            contents.removeAll(toRemove);
1278629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            if (removedFromFolder) {
1279629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                final Folder folder = getOpenFolder();
1280aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                if (folder != null)
1281aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                    folder.notifyDataSetChanged();
1282629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1283629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LiveFolderInfo) {
1284629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LiveFolderInfo info = (LiveFolderInfo) tag;
1285629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final Uri uri = info.uri;
1286629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final ProviderInfo providerInfo = manager.resolveContentProvider(
1287629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    uri.getAuthority(), 0);
1288629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy
1289f11079b11e98912ed56546eaa300efd06c6eb917Joe Onorato                            if (providerInfo != null) {
129064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
129164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(providerInfo.packageName)) {
129264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        // TODO: This should probably be done on a worker thread
129364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1294aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
129564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
129664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1297629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1298629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        } else if (tag instanceof LauncherAppWidgetInfo) {
1299629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
1300629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            final AppWidgetProviderInfo provider =
1301629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                                    widgets.getAppWidgetInfo(info.appWidgetId);
1302e1cc6c3745c9ba721b6ab888d74c9d9e1d13ea6aDaniel Sandler                            if (provider != null) {
130364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                for (String packageName: packageNames) {
130464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    if (packageName.equals(provider.provider.getPackageName())) {
130564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        // TODO: This should probably be done on a worker thread
130664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
1307aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                                        childrenToRemove.add(view);
130864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                    }
130964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
1310629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            }
1311574d20ec84551370987dde530c27ec493bdef564Romain Guy                        }
1312574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1313aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1314629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    childCount = childrenToRemove.size();
1315629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    for (int j = 0; j < childCount; j++) {
1316629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        View child = childrenToRemove.get(j);
1317629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.removeViewInLayout(child);
1318629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        if (child instanceof DropTarget) {
1319629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                            mDragController.removeDropTarget((DropTarget)child);
1320629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        }
1321574d20ec84551370987dde530c27ec493bdef564Romain Guy                    }
1322aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1323629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                    if (childCount > 0) {
1324629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.requestLayout();
1325629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy                        layout.invalidate();
13265c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
132731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
1328629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy            });
132931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
133031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1331f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
133264e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
13339c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final PackageManager pm = mLauncher.getPackageManager();
13349c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
1335dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        final int screenCount = getChildCount();
1336dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka        for (int i = 0; i < screenCount; i++) {
1337f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            final CellLayout layout = (CellLayout) getChildAt(i);
1338f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            int childCount = layout.getChildCount();
1339f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            for (int j = 0; j < childCount; j++) {
1340f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                final View view = layout.getChildAt(j);
1341f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                Object tag = view.getTag();
13420589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                if (tag instanceof ShortcutInfo) {
13430589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato                    ShortcutInfo info = (ShortcutInfo)tag;
1344f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // We need to check for ACTION_MAIN otherwise getComponent() might
1345f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // return null for some shortcuts (for instance, for shortcuts to
1346f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    // web pages.)
1347f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final Intent intent = info.intent;
1348f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    final ComponentName name = intent.getComponent();
1349f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
135064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
135164e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        final int appCount = apps.size();
1352aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                        for (int k = 0; k < appCount; k++) {
135364e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            ApplicationInfo app = apps.get(k);
135464e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                            if (app.componentName.equals(name)) {
135564e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                info.setIcon(mIconCache.getIcon(info.intent));
135664e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
135764e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
135864e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                        null, null);
135964e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                                }
136064e6be78dc72e1a89fe8fb95c502586f9260df28Joe Onorato                        }
1361f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                    }
1362f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project                }
1363f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
1364f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
1365f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
1366f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
136714f122bf847e50a3e7730ccbe57abc25d086a01bJoe Onorato    void moveToDefaultScreen(boolean animate) {
1368c45b16862918a0c6c253bba12032165b030565afJoe Onorato        if (animate) {
13694cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            if (mIsSmall) {
13700142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                unshrink(mDefaultPage);
13714cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            } else {
13720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka                snapToPage(mDefaultPage);
13734cb3724a2c1e5f278e1531d643accc40fcd8e219Michael Jurka            }
1374c45b16862918a0c6c253bba12032165b030565afJoe Onorato        } else {
13750142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka            setCurrentPage(mDefaultPage);
1376c45b16862918a0c6c253bba12032165b030565afJoe Onorato        }
13770142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        getChildAt(mDefaultPage).requestFocus();
137831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
137931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13808a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    void setIndicators(Drawable previous, Drawable next) {
13818a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mPreviousIndicator = previous;
13828a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy        mNextIndicator = next;
13830142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        previous.setLevel(mCurrentPage);
13840142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka        next.setLevel(mCurrentPage);
13858a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy    }
13868a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
13870142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
13880142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPages() {
13890142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    }
139031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13910142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    @Override
13920142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    public void syncPageItems(int page) {
139331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
13940142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
139531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
1396