Folder.java revision e601a43345224e3e386abc68bbea8b08b2df9570
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
19df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.Animator;
20df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.AnimatorListenerAdapter;
21df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.ObjectAnimator;
22df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.PropertyValuesHolder;
23df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.ValueAnimator;
24df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.ValueAnimator.AnimatorUpdateListener;
2531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
2676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.content.res.Resources;
27fb5411e98278d461b78aea0663d3e85f7a9e8a15Romain Guyimport android.graphics.Rect;
28badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohenimport android.graphics.drawable.Drawable;
297a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohenimport android.text.InputType;
30e601a43345224e3e386abc68bbea8b08b2df9570Adam Cohenimport android.text.Selection;
31e601a43345224e3e386abc68bbea8b08b2df9570Adam Cohenimport android.text.Spannable;
3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
3376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.ActionMode;
3476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.KeyEvent;
35df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.view.LayoutInflater;
3676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.Menu;
3776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.MenuItem;
380c872ba544ecfd9b106bb66137da8680927590deAdam Cohenimport android.view.MotionEvent;
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
402801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.view.animation.AccelerateInterpolator;
412801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohenimport android.view.animation.DecelerateInterpolator;
4276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.inputmethod.EditorInfo;
4376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.inputmethod.InputMethodManager;
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.LinearLayout;
45df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.widget.TextView;
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
47edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guyimport com.android.launcher.R;
48a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenimport com.android.launcher2.FolderInfo.FolderListener;
49edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
50c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohenimport java.util.ArrayList;
51c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen
5231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Represents a set of icons chosen by the user or generated by the system.
5431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
558dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohenpublic class Folder extends LinearLayout implements DragSource, View.OnClickListener,
568dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener {
5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
584eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen    private static final String TAG = "Launcher.Folder";
59df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
604eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen    protected DragController mDragController;
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected Launcher mLauncher;
6231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected FolderInfo mInfo;
6331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
64df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    static final int STATE_NONE = -1;
65df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    static final int STATE_SMALL = 0;
66df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    static final int STATE_ANIMATING = 1;
67df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    static final int STATE_OPEN = 2;
68df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
69df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    private int mExpandDuration;
70df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    protected CellLayout mContent;
71df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    private final LayoutInflater mInflater;
72df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    private final IconCache mIconCache;
73df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    private int mState = STATE_NONE;
742801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private static final int FULL_GROW = 0;
752801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private static final int PARTIAL_GROW = 1;
76bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private static final int REORDER_ANIMATION_DURATION = 230;
77bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private static final int ON_EXIT_CLOSE_DELAY = 800;
782801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private int mMode = PARTIAL_GROW;
792801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private boolean mRearrangeOnClose = false;
802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private FolderIcon mFolderIcon;
812801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private int mMaxCountX;
822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private int mMaxCountY;
832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private Rect mNewSize = new Rect();
843e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    private Rect mIconRect = new Rect();
857c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen    private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>();
86badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    private Drawable mIconDrawable;
877c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen    boolean mItemsInvalidated = false;
88bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private ShortcutInfo mCurrentDragInfo;
89bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private View mCurrentDragView;
90bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    boolean mSuppressOnAdd = false;
91bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private int[] mTargetCell = new int[2];
92bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private int[] mPreviousTargetCell = new int[2];
93bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private int[] mEmptyCell = new int[2];
94ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen    private int[] mTempXY = new int[2];
95bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private Alarm mReorderAlarm = new Alarm();
96bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private Alarm mOnExitAlarm = new Alarm();
9776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private TextView mFolderName;
9876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private int mFolderNameHeight;
994ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen    private Rect mHitRect = new Rect();
1008e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen    private Rect mTempRect = new Rect();
1018dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    private boolean mFirstOpen = true;
10276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
10376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private boolean mIsEditingName = false;
10476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private InputMethodManager mInputMethodManager;
105df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
106a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen    private static String sDefaultFolderName;
107a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen    private static String sHintText;
108a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen
10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to inflate the Workspace from XML.
11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param attrs The attribtues set containing the Workspace's customization values.
11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public Folder(Context context, AttributeSet attrs) {
11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        setAlwaysDrawnWithCacheEnabled(false);
118df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        mInflater = LayoutInflater.from(context);
119df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache();
1208e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        mMaxCountX = LauncherModel.getCellCountX();
1218e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        mMaxCountY = LauncherModel.getCellCountY();
12276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
12376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mInputMethodManager = (InputMethodManager)
12476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
12576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
12676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        Resources res = getResources();
12776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mExpandDuration = res.getInteger(R.integer.config_folderAnimDuration);
1284ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen
1294ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen        if (sDefaultFolderName == null) {
1304ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen            sDefaultFolderName = res.getString(R.string.folder_name);
1314ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen        }
132a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen        if (sHintText == null) {
133a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen            sHintText = res.getString(R.string.folder_hint_text);
134a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen        }
1354eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen
1364eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen        mLauncher = (Launcher) context;
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected void onFinishInflate() {
14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.onFinishInflate();
142df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        mContent = (CellLayout) findViewById(R.id.folder_content);
1432801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        mContent.setGridSize(0, 0);
14476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderName = (TextView) findViewById(R.id.folder_name);
14576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
14676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        // We find out how tall the text view wants to be (it is set to wrap_content), so that
14776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        // we can allocate the appropriate amount of space for it.
14876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        int measureSpec = MeasureSpec.UNSPECIFIED;
14976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderName.measure(measureSpec, measureSpec);
15076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderNameHeight = mFolderName.getMeasuredHeight();
15176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
15276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        // We disable action mode for now since it messes up the view on phones
15376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback);
15476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderName.setCursorVisible(false);
15576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderName.setOnEditorActionListener(this);
1564ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen        mFolderName.setSelectAllOnFocus(true);
1577a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohen        mFolderName.setInputType(mFolderName.getInputType() |
1587a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohen                InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
1602801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
16176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
16276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
16376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            return false;
16476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
16576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
16676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
16776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            return false;
16876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
16976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
17076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        public void onDestroyActionMode(ActionMode mode) {
17176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
17276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
17376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
17476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            return false;
17576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
17676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    };
17776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void onClick(View v) {
179df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        Object tag = v.getTag();
180df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        if (tag instanceof ShortcutInfo) {
181df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            // refactor this code from Folder
182df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            ShortcutInfo item = (ShortcutInfo) tag;
183df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            int[] pos = new int[2];
184df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            v.getLocationOnScreen(pos);
185df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            item.intent.setSourceBounds(new Rect(pos[0], pos[1],
186df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
187df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            mLauncher.startActivitySafely(item.intent, item);
188df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        }
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    public boolean onInterceptTouchEvent(MotionEvent ev) {
19276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
19376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            mFolderName.getHitRect(mHitRect);
19476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            if (mHitRect.contains((int) ev.getX(), (int) ev.getY()) && !mIsEditingName) {
19576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                startEditingFolderName();
19676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            }
19776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
19876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        return false;
19976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
20076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onLongClick(View v) {
202df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        Object tag = v.getTag();
203df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        if (tag instanceof ShortcutInfo) {
204df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            ShortcutInfo item = (ShortcutInfo) tag;
205df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            if (!v.isInTouchMode()) {
206df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen                return false;
207df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            }
208df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
209df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            mLauncher.getWorkspace().onDragStartedWithItem(v);
210ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen            mLauncher.getWorkspace().beginDragShared(v, this);
211badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen            mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
21276078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen
21376078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen            mCurrentDragInfo = item;
214bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mEmptyCell[0] = item.cellX;
215bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mEmptyCell[1] = item.cellY;
216bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mCurrentDragView = v;
217fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen
218fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen            mContent.removeView(mCurrentDragView);
219fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen            mInfo.remove(mCurrentDragInfo);
220df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        }
22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return true;
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    public boolean isEditingName() {
22576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        return mIsEditingName;
22676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
22776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
22876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    public void startEditingFolderName() {
229a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen        mFolderName.setHint("");
23076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderName.setCursorVisible(true);
23176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mIsEditingName = true;
23276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
23376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
23476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    public void dismissEditingName() {
23576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
23676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        doneEditingFolderName(true);
23776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
23876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
23976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    public void doneEditingFolderName(boolean commit) {
240a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen        mFolderName.setHint(sHintText);
24176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mInfo.setTitle(mFolderName.getText());
24276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        LauncherModel.updateItemInDatabase(mLauncher, mInfo);
24376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderName.setCursorVisible(false);
24476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mFolderName.clearFocus();
245e601a43345224e3e386abc68bbea8b08b2df9570Adam Cohen        Selection.setSelection((Spannable) mFolderName.getText(), 0, 0);
24676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        mIsEditingName = false;
24776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
24876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
24976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
25076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        if (actionId == EditorInfo.IME_ACTION_DONE) {
25176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            dismissEditingName();
25276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen            return true;
25376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        }
25476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        return false;
25576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
25676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
25776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    public View getEditTextRegion() {
25876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        return mFolderName;
25976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
26076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen
261badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    public Drawable getDragDrawable() {
262badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen        return mIconDrawable;
263badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen    }
264badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen
2650c872ba544ecfd9b106bb66137da8680927590deAdam Cohen    /**
2660c872ba544ecfd9b106bb66137da8680927590deAdam Cohen     * We need to handle touch events to prevent them from falling through to the workspace below.
2670c872ba544ecfd9b106bb66137da8680927590deAdam Cohen     */
2680c872ba544ecfd9b106bb66137da8680927590deAdam Cohen    @Override
2690c872ba544ecfd9b106bb66137da8680927590deAdam Cohen    public boolean onTouchEvent(MotionEvent ev) {
2700c872ba544ecfd9b106bb66137da8680927590deAdam Cohen        return true;
2710c872ba544ecfd9b106bb66137da8680927590deAdam Cohen    }
2720c872ba544ecfd9b106bb66137da8680927590deAdam Cohen
27300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragController(DragController dragController) {
27400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragController = dragController;
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2772801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    void setFolderIcon(FolderIcon icon) {
2782801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        mFolderIcon = icon;
2792801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
2802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
28231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @return the FolderInfo object associated with this folder
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    FolderInfo getInfo() {
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return mInfo;
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void onOpen() {
289df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        // When the folder opens, we need to refresh the GridView's selection by
290df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        // forcing a layout
291df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        // TODO: find out if this is still necessary
292df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        mContent.requestLayout();
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void onClose() {
2968e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        DragLayer parent = (DragLayer) getParent();
2978e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        parent.removeView(Folder.this);
29876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        clearFocus();
29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void bind(FolderInfo info) {
30231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mInfo = info;
303df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        ArrayList<ShortcutInfo> children = info.contents;
304c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>();
3057c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        setupContentForNumItems(children.size());
306df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        for (int i = 0; i < children.size(); i++) {
307df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            ShortcutInfo child = (ShortcutInfo) children.get(i);
308c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen            if (!createAndAddShortcut(child)) {
309c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen                overflow.add(child);
310c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen            }
311df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        }
312c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen
313c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        // If our folder has too many items we prune them from the list. This is an issue
314c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        // when upgrading from the old Folders implementation which could contain an unlimited
315c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        // number of items.
316c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        for (ShortcutInfo item: overflow) {
317c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen            mInfo.remove(item);
318c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen            LauncherModel.deleteItemFromDatabase(mLauncher, item);
319c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        }
320c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen
3214dbe6d993485a702505ee4895db94aaa89655f2cAdam Cohen        mItemsInvalidated = true;
322a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        mInfo.addListener(this);
3234ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen
324afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        if (!sDefaultFolderName.contentEquals(mInfo.title)) {
3254ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen            mFolderName.setText(mInfo.title);
3264ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen        } else {
3274ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen            mFolderName.setText("");
3284ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen        }
329df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
330df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
331df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    /**
332df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     * Creates a new UserFolder, inflated from R.layout.user_folder.
333df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     *
334df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     * @param context The application's context.
335df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     *
336df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     * @return A new UserFolder.
337df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     */
338df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    static Folder fromXml(Context context) {
339df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null);
340df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
341df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
342df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    /**
343df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     * This method is intended to make the UserFolder to be visually identical in size and position
344df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     * to its associated FolderIcon. This allows for a seamless transition into the expanded state.
345df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     */
346df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    private void positionAndSizeAsIcon() {
3473e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        if (!(getParent() instanceof DragLayer)) return;
348df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
3498e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
350df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
3512801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        if (mMode == PARTIAL_GROW) {
3522801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            setScaleX(0.8f);
3532801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            setScaleY(0.8f);
3542801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            setAlpha(0f);
3552801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        } else {
3563e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            mLauncher.getDragLayer().getDescendantRectRelativeToSelf(mFolderIcon, mIconRect);
3573e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            lp.width = mIconRect.width();
3583e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            lp.height = mIconRect.height();
3593e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            lp.x = mIconRect.left;
3603e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            lp.y = mIconRect.top;
3612801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            mContent.setAlpha(0);
3622801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
363df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        mState = STATE_SMALL;
364df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
365df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
366df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    public void animateOpen() {
3678dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        if (mFirstOpen) {
3688dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            setLayerType(LAYER_TYPE_HARDWARE, null);
3698dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            buildLayer();
3708dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            mFirstOpen = false;
3718dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        }
3728dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
3733e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        positionAndSizeAsIcon();
3743e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
3758e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        if (!(getParent() instanceof DragLayer)) return;
376df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
3772801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        ObjectAnimator oa;
3788e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
379df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
3802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        centerAboutIcon();
3812801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        if (mMode == PARTIAL_GROW) {
3822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1);
3832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
3842801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
3852801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
3862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        } else {
3872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width());
3882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height());
3892801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left);
3902801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top);
3912801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
3922801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            oa.addUpdateListener(new AnimatorUpdateListener() {
3932801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                public void onAnimationUpdate(ValueAnimator animation) {
3942801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                    requestLayout();
3952801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                }
3962801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            });
3972801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
3982801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f);
3992801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
4002801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            alphaOa.setDuration(mExpandDuration);
4012801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            alphaOa.setInterpolator(new AccelerateInterpolator(2.0f));
4022801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            alphaOa.start();
4032801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
404df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
4052801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        oa.addListener(new AnimatorListenerAdapter() {
406df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            @Override
407df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            public void onAnimationStart(Animator animation) {
408df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen                mState = STATE_ANIMATING;
409df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            }
410df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            @Override
411df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            public void onAnimationEnd(Animator animation) {
4122801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                mState = STATE_OPEN;
4138dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                setLayerType(LAYER_TYPE_NONE, null);
4148dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen                enableHardwareLayersForChildren();
415df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            }
416df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        });
4172801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        oa.setDuration(mExpandDuration);
4182801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        oa.start();
419df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
420df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
4218dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    void enableHardwareLayersForChildren() {
4228dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        ArrayList<View> children = getItemsInReadingOrder();
4238dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        for (View child: children) {
4248dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen            child.setLayerType(LAYER_TYPE_HARDWARE, null);
4258dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        }
4268dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    }
4278dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
428df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    public void animateClosed() {
4298e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        if (!(getParent() instanceof DragLayer)) return;
4308dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        setLayerType(LAYER_TYPE_HARDWARE, null);
4318dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        buildLayer();
432df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
4332801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        ObjectAnimator oa;
4342801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        if (mMode == PARTIAL_GROW) {
4352801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0);
4362801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f);
4372801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f);
4382801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY);
4392801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        } else {
4408e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen            DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
4412801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
4423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mIconRect.width());
4433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mIconRect.height());
4443e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mIconRect.left);
4453e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mIconRect.top);
4462801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y);
4472801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            oa.addUpdateListener(new AnimatorUpdateListener() {
4482801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                public void onAnimationUpdate(ValueAnimator animation) {
4492801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                    requestLayout();
4502801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                }
4512801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            });
4522801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
4532801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
4542801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha);
4552801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            alphaOa.setDuration(mExpandDuration);
4562801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            alphaOa.setInterpolator(new DecelerateInterpolator(2.0f));
4572801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            alphaOa.start();
4582801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
459df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
4602801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        oa.addListener(new AnimatorListenerAdapter() {
461df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            @Override
462df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            public void onAnimationEnd(Animator animation) {
46376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                onClose();
4642801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                onCloseComplete();
4652801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                mState = STATE_SMALL;
466df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            }
467df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            @Override
468df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            public void onAnimationStart(Animator animation) {
469df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen                mState = STATE_ANIMATING;
470df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            }
471df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        });
4722801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        oa.setDuration(mExpandDuration);
4732801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        oa.start();
474df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
475df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
476df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    void notifyDataSetChanged() {
477df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        // recreate all the children if the data set changes under us. We may want to do this more
478df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        // intelligently (ie just removing the views that should no longer exist)
479df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        mContent.removeAllViewsInLayout();
480df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        bind(mInfo);
481df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
482df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
483cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public boolean acceptDrop(DragObject d) {
484cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        final ItemInfo item = (ItemInfo) d.dragInfo;
485df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        final int itemType = item.itemType;
4862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
4872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                    itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) &&
4882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                    !isFull());
489df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
490df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
491df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    protected boolean findAndSetEmptyCells(ShortcutInfo item) {
492df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        int[] emptyCell = new int[2];
493df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) {
494df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            item.cellX = emptyCell[0];
495df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            item.cellY = emptyCell[1];
496df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            return true;
497df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        } else {
498df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            return false;
499df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        }
500df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
501df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
502c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen    protected boolean createAndAddShortcut(ShortcutInfo item) {
503df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        final TextView textView =
504e87b924efaaf1cfb555a4327dc653929a4c182f1Adam Cohen            (TextView) mInflater.inflate(R.layout.application, this, false);
505df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        textView.setCompoundDrawablesWithIntrinsicBounds(null,
506df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen                new FastBitmapDrawable(item.getIcon(mIconCache)), null, null);
507df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        textView.setText(item.title);
508df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        textView.setTag(item);
509df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
510df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        textView.setOnClickListener(this);
511df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        textView.setOnLongClickListener(this);
512df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
513c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        // We need to check here to verify that the given item's location isn't already occupied
514c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        // by another item. If it is, we need to find the next available slot and assign
515c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        // it that position. This is an issue when upgrading from the old Folders implementation
516c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        // which could contain an unlimited number of items.
517c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        if (mContent.getChildAt(item.cellX, item.cellY) != null) {
518c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen            if (!findAndSetEmptyCells(item)) {
519c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen                return false;
520c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen            }
521c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        }
522c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen
523df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        CellLayout.LayoutParams lp =
524df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen            new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY);
525df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        boolean insert = false;
526df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true);
527c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen        return true;
528df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
529df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
530cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public void onDragEnter(DragObject d) {
531bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mPreviousTargetCell[0] = -1;
532bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mPreviousTargetCell[1] = -1;
533bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mOnExitAlarm.cancelAlarm();
534df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
535df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
536bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    OnAlarmListener mReorderAlarmListener = new OnAlarmListener() {
537bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        public void onAlarm(Alarm alarm) {
538bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            realTimeReorder(mEmptyCell, mTargetCell);
539bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
540bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    };
541bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen
542bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    boolean readingOrderGreaterThan(int[] v1, int[] v2) {
543bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) {
544bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            return true;
545bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        } else {
546bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            return false;
547bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
548df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
549df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
550bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private void realTimeReorder(int[] empty, int[] target) {
551bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        boolean wrap;
552bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        int startX;
553bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        int endX;
554bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        int startY;
55576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        int delay = 0;
55676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen        float delayAmount = 30;
557bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (readingOrderGreaterThan(target, empty)) {
558bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            wrap = empty[0] >= mContent.getCountX() - 1;
559bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            startY = wrap ? empty[1] + 1 : empty[1];
560bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            for (int y = startY; y <= target[1]; y++) {
561bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                startX = y == empty[1] ? empty[0] + 1 : 0;
562bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                endX = y < target[1] ? mContent.getCountX() - 1 : target[0];
563bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                for (int x = startX; x <= endX; x++) {
564bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                    View v = mContent.getChildAt(x,y);
565bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                    if (mContent.animateChildToPosition(v, empty[0], empty[1],
56676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                            REORDER_ANIMATION_DURATION, delay)) {
567bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                        empty[0] = x;
568bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                        empty[1] = y;
56976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                        delay += delayAmount;
57076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                        delayAmount *= 0.9;
571bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                    }
572bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                }
573bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            }
574bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        } else {
575bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            wrap = empty[0] == 0;
576bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            startY = wrap ? empty[1] - 1 : empty[1];
577bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            for (int y = startY; y >= target[1]; y--) {
578bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1;
579bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                endX = y > target[1] ? 0 : target[0];
580bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                for (int x = startX; x >= endX; x--) {
581bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                    View v = mContent.getChildAt(x,y);
582bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                    if (mContent.animateChildToPosition(v, empty[0], empty[1],
58376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                            REORDER_ANIMATION_DURATION, delay)) {
584bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                        empty[0] = x;
585bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                        empty[1] = y;
58676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                        delay += delayAmount;
58776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen                        delayAmount *= 0.9;
588bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                    }
589bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                }
590bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            }
591bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
592bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    }
593bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen
594bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    public void onDragOver(DragObject d) {
595bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, null);
596bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1], 1, 1, mTargetCell);
597bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen
598bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (mTargetCell[0] != mPreviousTargetCell[0] || mTargetCell[1] != mPreviousTargetCell[1]) {
599bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mReorderAlarm.cancelAlarm();
600bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mReorderAlarm.setOnAlarmListener(mReorderAlarmListener);
601bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mReorderAlarm.setAlarm(150);
602bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mPreviousTargetCell[0] = mTargetCell[0];
603bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mPreviousTargetCell[1] = mTargetCell[1];
604bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
605df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
606df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
607bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    // This is used to compute the visual center of the dragView. The idea is that
608bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    // the visual center represents the user's interpretation of where the item is, and hence
609bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    // is the appropriate point to use when determining drop location.
610bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset,
611bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            DragView dragView, float[] recycle) {
612bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        float res[];
613bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (recycle == null) {
614bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            res = new float[2];
615bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        } else {
616bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            res = recycle;
617df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        }
6182801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
619bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        // These represent the visual top and left of drag view if a dragRect was provided.
620bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        // If a dragRect was not provided, then they correspond to the actual view left and
621bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        // top, as the dragRect is in that case taken to be the entire dragView.
622bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        // R.dimen.dragViewOffsetY.
623bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        int left = x - xOffset;
624bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        int top = y - yOffset;
625bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen
626bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        // In order to find the visual center, we shift by half the dragRect
627bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        res[0] = left + dragView.getDragRegion().width() / 2;
628bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        res[1] = top + dragView.getDragRegion().height() / 2;
629bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen
630bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        return res;
631bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    }
632bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen
633bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() {
634bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        public void onAlarm(Alarm alarm) {
6353e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            completeDragExit();
636bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
637bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    };
6382801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
63995bb800de9b0142bea0110b074eddbcf0e475736Adam Cohen    public void completeDragExit() {
6403e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mLauncher.closeFolder();
6413e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mCurrentDragInfo = null;
6423e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mCurrentDragView = null;
6433e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mSuppressOnAdd = false;
6443e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        mRearrangeOnClose = true;
6453e8f811f31a2275e778244427271f77f4116c08bAdam Cohen    }
6463e8f811f31a2275e778244427271f77f4116c08bAdam Cohen
647bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    public void onDragExit(DragObject d) {
648bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        // We only close the folder if this is a true drag exit, ie. not because a drop
649bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        // has occurred above the folder.
650bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (!d.dragComplete) {
651bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener);
652bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY);
653bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
654bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mReorderAlarm.cancelAlarm();
6552801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
6562801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
657c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen    public void onDropCompleted(View target, DragObject d, boolean success) {
658bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mCurrentDragInfo = null;
659bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mCurrentDragView = null;
660bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mSuppressOnAdd = false;
66176078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen        if (!success) {
66276078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen            if (d.dragView != null) {
66376078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen                if (target instanceof CellLayout) {
66476078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen                    // TODO: we should animate the item back to the folder in this case
66576078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen                }
66676078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen            }
667bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            // TODO: if the drag fails, we need to re-add the item
6683e8f811f31a2275e778244427271f77f4116c08bAdam Cohen        } else {
6693e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            if (target != this) {
6703e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                mOnExitAlarm.cancelAlarm();
6713e8f811f31a2275e778244427271f77f4116c08bAdam Cohen                completeDragExit();
6723e8f811f31a2275e778244427271f77f4116c08bAdam Cohen            }
67376078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen        }
674df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
675df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
676df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    public boolean isDropEnabled() {
677df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        return true;
678df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen    }
679df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen
680cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    public DropTarget getDropTargetDelegate(DragObject d) {
681df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        return null;
68231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
683a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
6842801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private void setupContentDimension(int count) {
6852801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        ArrayList<View> list = getItemsInReadingOrder();
6862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
6872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int countX = mContent.getCountX();
6882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int countY = mContent.getCountY();
6897c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        boolean done = false;
6907c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen
6917c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        while (!done) {
6927c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            int oldCountX = countX;
6937c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            int oldCountY = countY;
6947c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            if (countX * countY < count) {
6957c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                // Current grid is too small, expand it
6967c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                if (countX <= countY && countX < mMaxCountX) {
6977c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                    countX++;
6987c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                } else if (countY < mMaxCountY) {
6997c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                    countY++;
7007c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                }
7017c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                if (countY == 0) countY++;
7027c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            } else if ((countY - 1) * countX >= count && countY >= countX) {
7037c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                countY = Math.max(0, countY - 1);
7047c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            } else if ((countX - 1) * countY >= count) {
7057c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                countX = Math.max(0, countX - 1);
7062801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            }
7077c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            done = countX == oldCountX && countY == oldCountY;
7082801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
7097c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        mContent.setGridSize(countX, countY);
7102801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        arrangeChildren(list);
7112801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
7122801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
7132801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    public boolean isFull() {
7142801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        return getItemCount() >= mMaxCountX * mMaxCountY;
7152801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
7162801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
7172801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private void centerAboutIcon() {
7188e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
7192801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
7202801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
721f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen        int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight()
722f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen                + mFolderNameHeight;
7238e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        DragLayer parent = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
7248e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen
7258e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect);
7262801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
7278e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        int centerX = mTempRect.centerX();
7288e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        int centerY = mTempRect.centerY();
7292801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int centeredLeft = centerX - width / 2;
7302801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int centeredTop = centerY - height / 2;
7312801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
73235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        // We first fetch the currently visible CellLayoutChildren
7333d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        CellLayout currentPage = mLauncher.getWorkspace().getCurrentDropLayout();
73435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        CellLayoutChildren boundingLayout = currentPage.getChildrenLayout();
73535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        Rect bounds = new Rect();
73635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        parent.getDescendantRectRelativeToSelf(boundingLayout, bounds);
73735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen
73835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        // We need to bound the folder to the currently visible CellLayoutChildren
73935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        int left = Math.min(Math.max(bounds.left, centeredLeft),
74035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen                bounds.left + bounds.width() - width);
74135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        int top = Math.min(Math.max(bounds.top, centeredTop),
74235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen                bounds.top + bounds.height() - height);
74335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        // If the folder doesn't fit within the bounds, center it about the desired bounds
74435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        if (width >= bounds.width()) {
74535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen            left = bounds.left + (bounds.width() - width) / 2;
74635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        }
74735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen        if (height >= bounds.height()) {
74835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen            top = bounds.top + (bounds.height() - height) / 2;
7490e4857c302da6adbd45231d7a8bae0289fa33250Adam Cohen        }
7502801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
7512801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int folderPivotX = width / 2 + (centeredLeft - left);
7522801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int folderPivotY = height / 2 + (centeredTop - top);
7532801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        setPivotX(folderPivotX);
7542801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        setPivotY(folderPivotY);
7552801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
7562801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                (1.0f * folderPivotX / width));
7572801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
7582801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen                (1.0f * folderPivotY / height));
7592801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        mFolderIcon.setPivotX(folderIconPivotX);
7602801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        mFolderIcon.setPivotY(folderIconPivotY);
7612801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
7622801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        if (mMode == PARTIAL_GROW) {
7632801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            lp.width = width;
7642801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            lp.height = height;
7652801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            lp.x = left;
7662801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            lp.y = top;
7672801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        } else {
7682801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            mNewSize.set(left, top, left + width, top + height);
7692801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
7702801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
7712801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
7722801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private void setupContentForNumItems(int count) {
7732801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        setupContentDimension(count);
7742801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
7758e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
7762801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        if (lp == null) {
7778e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen            lp = new DragLayer.LayoutParams(0, 0);
7788e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen            lp.customPosition = true;
7792801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            setLayoutParams(lp);
7802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
7812801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        centerAboutIcon();
7822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
7832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
784234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
785234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
786f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen        int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight()
787f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen                + mFolderNameHeight;
788234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen
789234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        int contentWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(),
790234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen                MeasureSpec.EXACTLY);
791234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        int contentHeightSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredHeight(),
792234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen                MeasureSpec.EXACTLY);
793234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        mContent.measure(contentWidthSpec, contentHeightSpec);
794234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen
795234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        mFolderName.measure(contentWidthSpec,
796234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen                MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
797234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen        setMeasuredDimension(width, height);
798234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen    }
799234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen
8002801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private void arrangeChildren(ArrayList<View> list) {
8012801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        int[] vacant = new int[2];
8022801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        if (list == null) {
8032801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            list = getItemsInReadingOrder();
8042801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
8052801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        mContent.removeAllViews();
8062801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
8072801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        for (int i = 0; i < list.size(); i++) {
8082801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            View v = list.get(i);
8092801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            mContent.getVacantCell(vacant, 1, 1);
8102801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams();
8112801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            lp.cellX = vacant[0];
8122801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            lp.cellY = vacant[1];
8132801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            ItemInfo info = (ItemInfo) v.getTag();
8142801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            info.cellX = vacant[0];
8152801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            info.cellY = vacant[1];
8162801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            boolean insert = false;
8172801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true);
8187c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0,
8197c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                    info.cellX, info.cellY);
8202801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
8217c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        mItemsInvalidated = true;
8222801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
8232801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
824a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    public int getItemCount() {
825a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        return mContent.getChildrenLayout().getChildCount();
826a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    }
827a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
828a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    public View getItemAt(int index) {
829a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        return mContent.getChildrenLayout().getChildAt(index);
830a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    }
831a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen
8322801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    private void onCloseComplete() {
8332801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        if (mRearrangeOnClose) {
8342801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            setupContentForNumItems(getItemCount());
8352801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            mRearrangeOnClose = false;
8362801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
837afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        if (getItemCount() <= 1) {
838afb01ee74243cede19088e694ca82cea5983c603Adam Cohen            replaceFolderWithFinalItem();
839afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        }
840afb01ee74243cede19088e694ca82cea5983c603Adam Cohen    }
841afb01ee74243cede19088e694ca82cea5983c603Adam Cohen
842afb01ee74243cede19088e694ca82cea5983c603Adam Cohen    private void replaceFolderWithFinalItem() {
843afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        ItemInfo finalItem = null;
844afb01ee74243cede19088e694ca82cea5983c603Adam Cohen
845afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        if (getItemCount() == 1) {
846afb01ee74243cede19088e694ca82cea5983c603Adam Cohen            finalItem = mInfo.contents.get(0);
847afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        }
848afb01ee74243cede19088e694ca82cea5983c603Adam Cohen
849afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        // Remove the folder completely
8503d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screen);
851afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        cellLayout.removeView(mFolderIcon);
852afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        if (mFolderIcon instanceof DropTarget) {
853afb01ee74243cede19088e694ca82cea5983c603Adam Cohen            mDragController.removeDropTarget((DropTarget) mFolderIcon);
854afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        }
855afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        mLauncher.removeFolder(mInfo);
856afb01ee74243cede19088e694ca82cea5983c603Adam Cohen
857afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        if (finalItem != null) {
8583d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung            LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
8593d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung                    mInfo.screen, mInfo.cellX, mInfo.cellY);
860afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        }
861716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen        LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
862afb01ee74243cede19088e694ca82cea5983c603Adam Cohen
863afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        // Add the last remaining child to the workspace in place of the folder
864afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        if (finalItem != null) {
865afb01ee74243cede19088e694ca82cea5983c603Adam Cohen            View child = mLauncher.createShortcut(R.layout.application, cellLayout,
866afb01ee74243cede19088e694ca82cea5983c603Adam Cohen                    (ShortcutInfo) finalItem);
867afb01ee74243cede19088e694ca82cea5983c603Adam Cohen
8683d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung            mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screen, mInfo.cellX,
8693d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung                    mInfo.cellY, mInfo.spanX, mInfo.spanY);
870afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        }
8712801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen    }
8722801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen
873bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    public void onDrop(DragObject d) {
874bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        ShortcutInfo item;
875bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (d.dragInfo instanceof ApplicationInfo) {
876bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            // Came from all apps -- make a copy
877bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            item = ((ApplicationInfo) d.dragInfo).makeShortcut();
878bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            item.spanX = 1;
879bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            item.spanY = 1;
880bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        } else {
881bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            item = (ShortcutInfo) d.dragInfo;
882bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
883bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        // Dragged from self onto self
884bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (item == mCurrentDragInfo) {
885bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag();
886bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams();
887bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            si.cellX = lp.cellX = mEmptyCell[0];
888bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            si.cellX = lp.cellY = mEmptyCell[1];
889bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true);
890fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen            if (d.dragView.hasDrawn()) {
891fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen                mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView);
892fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen            } else {
893fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen                mCurrentDragView.setVisibility(VISIBLE);
894fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen            }
895e9166b247addcf67542ababb9d453f5bfb33c7b2Adam Cohen            mItemsInvalidated = true;
896bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            setupContentDimension(getItemCount());
897716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen            mSuppressOnAdd = true;
898bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
899bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mInfo.add(item);
900bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    }
901bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen
902bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    public void onAdd(ShortcutInfo item) {
903bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mItemsInvalidated = true;
904bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (mSuppressOnAdd) return;
905bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (!findAndSetEmptyCells(item)) {
906bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            // The current layout is full, can we expand it?
907bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            setupContentForNumItems(getItemCount() + 1);
908bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            findAndSetEmptyCells(item);
909bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        }
910bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        createAndAddShortcut(item);
911bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        LauncherModel.addOrMoveItemInDatabase(
912bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen                mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
913bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen    }
914bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen
915a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    public void onRemove(ShortcutInfo item) {
9167c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        mItemsInvalidated = true;
917bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        if (item == mCurrentDragInfo) return;
918df1e4e868a1970b756486dadd652651d40276d36Adam Cohen        View v = getViewForInfo(item);
919a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen        mContent.removeView(v);
9202801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        if (mState == STATE_ANIMATING) {
9212801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            mRearrangeOnClose = true;
9222801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        } else {
9232801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen            setupContentForNumItems(getItemCount());
9242801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen        }
925afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        if (getItemCount() <= 1) {
926afb01ee74243cede19088e694ca82cea5983c603Adam Cohen            replaceFolderWithFinalItem();
927afb01ee74243cede19088e694ca82cea5983c603Adam Cohen        }
928a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen    }
9297c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen
930df1e4e868a1970b756486dadd652651d40276d36Adam Cohen    private View getViewForInfo(ShortcutInfo item) {
931df1e4e868a1970b756486dadd652651d40276d36Adam Cohen        for (int j = 0; j < mContent.getCountY(); j++) {
932df1e4e868a1970b756486dadd652651d40276d36Adam Cohen            for (int i = 0; i < mContent.getCountX(); i++) {
933df1e4e868a1970b756486dadd652651d40276d36Adam Cohen                View v = mContent.getChildAt(i, j);
934df1e4e868a1970b756486dadd652651d40276d36Adam Cohen                if (v.getTag() == item) {
935df1e4e868a1970b756486dadd652651d40276d36Adam Cohen                    return v;
936df1e4e868a1970b756486dadd652651d40276d36Adam Cohen                }
937df1e4e868a1970b756486dadd652651d40276d36Adam Cohen            }
938df1e4e868a1970b756486dadd652651d40276d36Adam Cohen        }
939df1e4e868a1970b756486dadd652651d40276d36Adam Cohen        return null;
940df1e4e868a1970b756486dadd652651d40276d36Adam Cohen    }
941df1e4e868a1970b756486dadd652651d40276d36Adam Cohen
94276078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen    public void onItemsChanged() {
94376078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen    }
94476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    public void onTitleChanged(CharSequence title) {
94576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen    }
94676078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen
9477c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen    public ArrayList<View> getItemsInReadingOrder() {
94876078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen        return getItemsInReadingOrder(true);
94976078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen    }
95076078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen
95176078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen    public ArrayList<View> getItemsInReadingOrder(boolean includeCurrentDragItem) {
9527c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        if (mItemsInvalidated) {
9537c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            mItemsInReadingOrder.clear();
9547c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            for (int j = 0; j < mContent.getCountY(); j++) {
9557c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                for (int i = 0; i < mContent.getCountX(); i++) {
9567c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                    View v = mContent.getChildAt(i, j);
9577c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                    if (v != null) {
95876078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen                        ShortcutInfo info = (ShortcutInfo) v.getTag();
95976078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen                        if (info != mCurrentDragInfo || includeCurrentDragItem) {
96076078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen                            mItemsInReadingOrder.add(v);
96176078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen                        }
9627c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                    }
9637c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen                }
9647c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            }
9657c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen            mItemsInvalidated = false;
9667c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        }
9677c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen        return mItemsInReadingOrder;
9687c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen    }
9698dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen
9708dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    public void getLocationInDragLayer(int[] loc) {
9718dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen        mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
9728dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen    }
97331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
974