Folder.java revision f3007589e346df224d357b389069adfeb266545e
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 17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3; 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; 2331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context; 2476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.content.res.Resources; 25043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.PointF; 26fb5411e98278d461b78aea0663d3e85f7a9e8a15Romain Guyimport android.graphics.Rect; 27badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohenimport android.graphics.drawable.Drawable; 287a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohenimport android.text.InputType; 29e601a43345224e3e386abc68bbea8b08b2df9570Adam Cohenimport android.text.Selection; 30e601a43345224e3e386abc68bbea8b08b2df9570Adam Cohenimport android.text.Spannable; 3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet; 323bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohenimport android.util.Log; 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; 403371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityEvent; 413371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohenimport android.view.accessibility.AccessibilityManager; 422e7471cf96bb8d9d02a9f2010ec198d585363dd7Mindy DelliCarpiniimport android.view.animation.AccelerateInterpolator; 432e7471cf96bb8d9d02a9f2010ec198d585363dd7Mindy DelliCarpiniimport android.view.animation.Interpolator; 4476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.inputmethod.EditorInfo; 4576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.inputmethod.InputMethodManager; 4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.LinearLayout; 47f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohenimport android.widget.ScrollView; 48df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.widget.TextView; 4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 50325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerimport com.android.launcher3.FolderInfo.FolderListener; 51edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy 52c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohenimport java.util.ArrayList; 533bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohenimport java.util.Collections; 543bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohenimport java.util.Comparator; 55c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen 5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/** 5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Represents a set of icons chosen by the user or generated by the system. 5831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 598dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohenpublic class Folder extends LinearLayout implements DragSource, View.OnClickListener, 60ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener, 61ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen View.OnFocusChangeListener { 624eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen private static final String TAG = "Launcher.Folder"; 63df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 644eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen protected DragController mDragController; 6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected Launcher mLauncher; 6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected FolderInfo mInfo; 6731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 68df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static final int STATE_NONE = -1; 69df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static final int STATE_SMALL = 0; 70df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static final int STATE_ANIMATING = 1; 71df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static final int STATE_OPEN = 2; 72df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 73df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private int mExpandDuration; 74df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen protected CellLayout mContent; 75f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private ScrollView mScrollView; 76df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private final LayoutInflater mInflater; 77df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private final IconCache mIconCache; 78df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private int mState = STATE_NONE; 79bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private static final int REORDER_ANIMATION_DURATION = 230; 80f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private static final int REORDER_DELAY = 250; 81bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private static final int ON_EXIT_CLOSE_DELAY = 800; 822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private boolean mRearrangeOnClose = false; 832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private FolderIcon mFolderIcon; 842801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private int mMaxCountX; 852801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private int mMaxCountY; 86f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private int mMaxVisibleX; 87f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private int mMaxVisibleY; 88f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private int mMaxContentAreaHeight = 0; 8978dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen private int mMaxNumItems; 907c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); 91badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen private Drawable mIconDrawable; 927c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen boolean mItemsInvalidated = false; 93bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private ShortcutInfo mCurrentDragInfo; 94bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private View mCurrentDragView; 95bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen boolean mSuppressOnAdd = false; 96bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private int[] mTargetCell = new int[2]; 97bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private int[] mPreviousTargetCell = new int[2]; 98bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private int[] mEmptyCell = new int[2]; 99bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private Alarm mReorderAlarm = new Alarm(); 100bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private Alarm mOnExitAlarm = new Alarm(); 10176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private int mFolderNameHeight; 1028e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen private Rect mTempRect = new Rect(); 10367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen private boolean mDragInProgress = false; 10467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen private boolean mDeleteFolderOnDropCompleted = false; 10567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen private boolean mSuppressFolderDeletion = false; 10605e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen private boolean mItemAddedBackToSelfViaIcon = false; 107ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen FolderEditText mFolderName; 108268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen private float mFolderIconPivotX; 109268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen private float mFolderIconPivotY; 110228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 111f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private static final int SCROLL_CUT_OFF_AMOUNT = 60; 1122e7471cf96bb8d9d02a9f2010ec198d585363dd7Mindy DelliCarpini 11353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini private static final float MAX_SCROLL_VELOCITY = 1500f; 114f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 11576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private boolean mIsEditingName = false; 11676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private InputMethodManager mInputMethodManager; 117df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 118a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen private static String sDefaultFolderName; 119a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen private static String sHintText; 120a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen 121f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private int DRAG_MODE_NONE = 0; 122f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private int DRAG_MODE_REORDER = 1; 123f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private int mDragMode = DRAG_MODE_NONE; 124f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 125fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen private boolean mDestroyed; 126fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 12753b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini private AutoScroller mAutoScroller; 12853b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini 1291e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka private Runnable mDeferredAction; 1301e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka private boolean mDeferDropAfterUninstall; 1311e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka private boolean mUninstallSuccessful; 1321e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka 13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Used to inflate the Workspace from XML. 13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param context The application's context. 13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param attrs The attribtues set containing the Workspace's customization values. 13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public Folder(Context context, AttributeSet attrs) { 14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, attrs); 1415f8afe6280eae34620067696173e71943e1a30a3Winson Chung 1425f8afe6280eae34620067696173e71943e1a30a3Winson Chung LauncherAppState app = LauncherAppState.getInstance(); 1435f8afe6280eae34620067696173e71943e1a30a3Winson Chung DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); 14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project setAlwaysDrawnWithCacheEnabled(false); 145df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mInflater = LayoutInflater.from(context); 1465f8afe6280eae34620067696173e71943e1a30a3Winson Chung mIconCache = app.getIconCache(); 14778dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen 14878dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen Resources res = getResources(); 1495f8afe6280eae34620067696173e71943e1a30a3Winson Chung mMaxCountX = mMaxVisibleX = mMaxVisibleY = (int) (grid.numColumns); 1505f8afe6280eae34620067696173e71943e1a30a3Winson Chung mMaxCountY = mMaxNumItems = Integer.MAX_VALUE; 15176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 15276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mInputMethodManager = (InputMethodManager) 1538b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 15476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 15576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mExpandDuration = res.getInteger(R.integer.config_folderAnimDuration); 1564ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen 1574ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen if (sDefaultFolderName == null) { 1584ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen sDefaultFolderName = res.getString(R.string.folder_name); 1594ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } 160a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen if (sHintText == null) { 161a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen sHintText = res.getString(R.string.folder_hint_text); 162a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen } 1634eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen mLauncher = (Launcher) context; 164ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // We need this view to be focusable in touch mode so that when text editing of the folder 165ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // name is complete, we have something to focus on, thus hiding the cursor and giving 166ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // reliable behvior when clicking the text field (since it will always gain focus on click). 167ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen setFocusableInTouchMode(true); 16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected void onFinishInflate() { 17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super.onFinishInflate(); 173f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mScrollView = (ScrollView) findViewById(R.id.scroll_view); 174df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mContent = (CellLayout) findViewById(R.id.folder_content); 175f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 1765f8afe6280eae34620067696173e71943e1a30a3Winson Chung LauncherAppState app = LauncherAppState.getInstance(); 1775f8afe6280eae34620067696173e71943e1a30a3Winson Chung DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); 1785f8afe6280eae34620067696173e71943e1a30a3Winson Chung 179f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen // Beyond this height, the area scrolls 1805f8afe6280eae34620067696173e71943e1a30a3Winson Chung mContent.setCellDimensions(grid.folderCellWidthPx, grid.folderCellHeightPx); 181f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mContent.setGridSize(mMaxVisibleX, mMaxVisibleY); 182f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxContentAreaHeight = mContent.getDesiredHeight() - SCROLL_CUT_OFF_AMOUNT; 1832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.setGridSize(0, 0); 184a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false); 1852374abfda3e53f84e005df8923170308e4df8c03Adam Cohen mContent.setInvertIfRtl(true); 186ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName = (FolderEditText) findViewById(R.id.folder_name); 187ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setFolder(this); 188ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen mFolderName.setOnFocusChangeListener(this); 18976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 19076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // We find out how tall the text view wants to be (it is set to wrap_content), so that 19176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // we can allocate the appropriate amount of space for it. 19276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen int measureSpec = MeasureSpec.UNSPECIFIED; 19376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.measure(measureSpec, measureSpec); 19476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderNameHeight = mFolderName.getMeasuredHeight(); 19576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 19676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // We disable action mode for now since it messes up the view on phones 19776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback); 19876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.setOnEditorActionListener(this); 1994ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setSelectAllOnFocus(true); 2007a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohen mFolderName.setInputType(mFolderName.getInputType() | 2017a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohen InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS); 20253b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mAutoScroller = new AutoScroller(mScrollView); 20353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mAutoScroller.setMaximumVelocityAbsolute(MAX_SCROLL_VELOCITY, MAX_SCROLL_VELOCITY); 20453b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mAutoScroller.setExtendsBeyondEdges(false); 20531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 2062801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 20776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { 20876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 20976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 21076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 21176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 21276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onCreateActionMode(ActionMode mode, Menu menu) { 21376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 21476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 21576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 21676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void onDestroyActionMode(ActionMode mode) { 21776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 21876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 21976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 22076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 22176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 22276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen }; 22376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void onClick(View v) { 225df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen Object tag = v.getTag(); 226df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (tag instanceof ShortcutInfo) { 227b5fe60c8a502fb7e265e3183550478b2b2a49264Adam Cohen mLauncher.onClick(v); 228df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean onLongClick(View v) { 23236a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung // Return if global dragging is not enabled 23336a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung if (!mLauncher.isDraggingEnabled()) return true; 23436a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung 235df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen Object tag = v.getTag(); 236df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (tag instanceof ShortcutInfo) { 237df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ShortcutInfo item = (ShortcutInfo) tag; 238df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (!v.isInTouchMode()) { 239df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return false; 240df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 241df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 2427d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung mLauncher.dismissFolderCling(null); 2437d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung 244df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mLauncher.getWorkspace().onDragStartedWithItem(v); 245ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen mLauncher.getWorkspace().beginDragShared(v, this); 246badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen mIconDrawable = ((TextView) v).getCompoundDrawables()[1]; 24776078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen 24876078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen mCurrentDragInfo = item; 249bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mEmptyCell[0] = item.cellX; 250bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mEmptyCell[1] = item.cellY; 251bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragView = v; 252fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen 253fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mContent.removeView(mCurrentDragView); 254fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mInfo.remove(mCurrentDragInfo); 25567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDragInProgress = true; 25605e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = false; 257df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return true; 25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 26176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean isEditingName() { 26276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return mIsEditingName; 26376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 26476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 26576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void startEditingFolderName() { 266a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen mFolderName.setHint(""); 26776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mIsEditingName = true; 26876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 26976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 27076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void dismissEditingName() { 27176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 27276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen doneEditingFolderName(true); 27376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 27476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 27576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void doneEditingFolderName(boolean commit) { 276a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen mFolderName.setHint(sHintText); 2771df26a368a135395b7bd61e9b109044b33b1b0beAdam Cohen // Convert to a string here to ensure that no other state associated with the text field 2781df26a368a135395b7bd61e9b109044b33b1b0beAdam Cohen // gets saved. 2793371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen String newTitle = mFolderName.getText().toString(); 2803371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mInfo.setTitle(newTitle); 28176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen LauncherModel.updateItemInDatabase(mLauncher, mInfo); 282ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 2833371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (commit) { 2843371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 2858b805b17158886035b38261eb611d8641701ae43Michael Jurka String.format(getContext().getString(R.string.folder_renamed), newTitle)); 2863371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 287ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // In order to clear the focus from the text field, we set the focus on ourself. This 288ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // ensures that every time the field is clicked, focus is gained, giving reliable behavior. 289ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen requestFocus(); 290ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 291e601a43345224e3e386abc68bbea8b08b2df9570Adam Cohen Selection.setSelection((Spannable) mFolderName.getText(), 0, 0); 29276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mIsEditingName = false; 29376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 29476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 29576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 29676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen if (actionId == EditorInfo.IME_ACTION_DONE) { 29776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen dismissEditingName(); 29876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return true; 29976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 30076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 30176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 30276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 30376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public View getEditTextRegion() { 30476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return mFolderName; 30576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 30676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 307badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen public Drawable getDragDrawable() { 308badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen return mIconDrawable; 309badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen } 310badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 3110c872ba544ecfd9b106bb66137da8680927590deAdam Cohen /** 3120c872ba544ecfd9b106bb66137da8680927590deAdam Cohen * We need to handle touch events to prevent them from falling through to the workspace below. 3130c872ba544ecfd9b106bb66137da8680927590deAdam Cohen */ 3140c872ba544ecfd9b106bb66137da8680927590deAdam Cohen @Override 3150c872ba544ecfd9b106bb66137da8680927590deAdam Cohen public boolean onTouchEvent(MotionEvent ev) { 3160c872ba544ecfd9b106bb66137da8680927590deAdam Cohen return true; 3170c872ba544ecfd9b106bb66137da8680927590deAdam Cohen } 3180c872ba544ecfd9b106bb66137da8680927590deAdam Cohen 31900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void setDragController(DragController dragController) { 32000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragController = dragController; 32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3232801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen void setFolderIcon(FolderIcon icon) { 3242801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mFolderIcon = icon; 3252801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 3262801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 3273371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen @Override 3283371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 3293371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen // When the folder gets focus, we don't want to announce the list of items. 3303371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 3313371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 3323371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @return the FolderInfo object associated with this folder 33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project FolderInfo getInfo() { 33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return mInfo; 33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3403bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen private class GridComparator implements Comparator<ShortcutInfo> { 3413bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int mNumCols; 3423bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen public GridComparator(int numCols) { 3433bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen mNumCols = numCols; 3443bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3453bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 3463bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen @Override 3473bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen public int compare(ShortcutInfo lhs, ShortcutInfo rhs) { 3483bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int lhIndex = lhs.cellY * mNumCols + lhs.cellX; 3493bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int rhIndex = rhs.cellY * mNumCols + rhs.cellX; 3503bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen return (lhIndex - rhIndex); 3513bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3523bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3533bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 3543bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen private void placeInReadingOrder(ArrayList<ShortcutInfo> items) { 3553bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int maxX = 0; 3563bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int count = items.size(); 3573bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen for (int i = 0; i < count; i++) { 3583bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen ShortcutInfo item = items.get(i); 3593bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen if (item.cellX > maxX) { 3603bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen maxX = item.cellX; 3613bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3623bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 363691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen 364691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen GridComparator gridComparator = new GridComparator(maxX + 1); 3653bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen Collections.sort(items, gridComparator); 3663bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen final int countX = mContent.getCountX(); 3673bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen for (int i = 0; i < count; i++) { 3683bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int x = i % countX; 3693bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int y = i / countX; 3703bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen ShortcutInfo item = items.get(i); 3713bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen item.cellX = x; 3723bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen item.cellY = y; 3733bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3743bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3753bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project void bind(FolderInfo info) { 37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mInfo = info; 378df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ArrayList<ShortcutInfo> children = info.contents; 379c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>(); 3807c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen setupContentForNumItems(children.size()); 3813bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen placeInReadingOrder(children); 3820057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen int count = 0; 383df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen for (int i = 0; i < children.size(); i++) { 384df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ShortcutInfo child = (ShortcutInfo) children.get(i); 385c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen if (!createAndAddShortcut(child)) { 386c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen overflow.add(child); 3870057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen } else { 3880057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen count++; 389c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 390df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 391c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 3920057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen // We rearrange the items in case there are any empty gaps 3930057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen setupContentForNumItems(count); 3940057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen 395c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // If our folder has too many items we prune them from the list. This is an issue 396c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // when upgrading from the old Folders implementation which could contain an unlimited 397c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // number of items. 398c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen for (ShortcutInfo item: overflow) { 399c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen mInfo.remove(item); 400c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen LauncherModel.deleteItemFromDatabase(mLauncher, item); 401c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 402c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 4034dbe6d993485a702505ee4895db94aaa89655f2cAdam Cohen mItemsInvalidated = true; 404ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen updateTextViewFocus(); 405a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen mInfo.addListener(this); 4064ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen 407afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (!sDefaultFolderName.contentEquals(mInfo.title)) { 4084ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setText(mInfo.title); 4094ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } else { 4104ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setText(""); 4114ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } 412691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen updateItemLocationsInDatabase(); 413df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 414df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 415df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen /** 416df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * Creates a new UserFolder, inflated from R.layout.user_folder. 417df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * 418df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * @param context The application's context. 419df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * 420df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * @return A new UserFolder. 421df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen */ 422df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static Folder fromXml(Context context) { 423df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null); 424df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 425df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 426df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen /** 427df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * This method is intended to make the UserFolder to be visually identical in size and position 428df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * to its associated FolderIcon. This allows for a seamless transition into the expanded state. 429df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen */ 430df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private void positionAndSizeAsIcon() { 4313e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (!(getParent() instanceof DragLayer)) return; 432662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setScaleX(0.8f); 433662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setScaleY(0.8f); 434662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setAlpha(0f); 435df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_SMALL; 436df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 437df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 438df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void animateOpen() { 4393e8f811f31a2275e778244427271f77f4116c08bAdam Cohen positionAndSizeAsIcon(); 4403e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 4418e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen if (!(getParent() instanceof DragLayer)) return; 4422801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen centerAboutIcon(); 443662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1); 444662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f); 445662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f); 446032e6bad1ba588ed8a884fb8f28fb8596efac480Michael Jurka final ObjectAnimator oa = 4472ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); 4486441de0ec2a71862798dd51180d0811b42edd514Adam Cohen 4492801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.addListener(new AnimatorListenerAdapter() { 450df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 451df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationStart(Animator animation) { 4523371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 4538b805b17158886035b38261eb611d8641701ae43Michael Jurka String.format(getContext().getString(R.string.folder_opened), 4543371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mContent.getCountX(), mContent.getCountY())); 455df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_ANIMATING; 456df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 457df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 458df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationEnd(Animator animation) { 4592801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mState = STATE_OPEN; 4600121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_NONE, null); 4617a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung Cling cling = mLauncher.showFirstRunFoldersCling(); 4627a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung if (cling != null) { 4637a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung cling.bringToFront(); 4647a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung } 465ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen setFocusOnFirstChild(); 466df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 467df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen }); 4682801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.setDuration(mExpandDuration); 4690121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_HARDWARE, null); 470f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka oa.start(); 471df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 472df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 4733371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private void sendCustomAccessibilityEvent(int type, String text) { 4748b805b17158886035b38261eb611d8641701ae43Michael Jurka AccessibilityManager accessibilityManager = (AccessibilityManager) 4758b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 4768b805b17158886035b38261eb611d8641701ae43Michael Jurka if (accessibilityManager.isEnabled()) { 4773371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen AccessibilityEvent event = AccessibilityEvent.obtain(type); 4783371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen onInitializeAccessibilityEvent(event); 4793371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen event.getText().add(text); 4808b805b17158886035b38261eb611d8641701ae43Michael Jurka accessibilityManager.sendAccessibilityEvent(event); 4813371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 4823371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 4833371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 484ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private void setFocusOnFirstChild() { 485ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View firstChild = mContent.getChildAt(0, 0); 486ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (firstChild != null) { 487ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen firstChild.requestFocus(); 488ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 489ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 490ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 491df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void animateClosed() { 4928e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen if (!(getParent() instanceof DragLayer)) return; 493662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0); 494662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f); 495662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f); 496032e6bad1ba588ed8a884fb8f28fb8596efac480Michael Jurka final ObjectAnimator oa = 4972ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); 498df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 4992801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.addListener(new AnimatorListenerAdapter() { 500df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 501df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationEnd(Animator animation) { 5022801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen onCloseComplete(); 5030121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_NONE, null); 5042801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mState = STATE_SMALL; 505df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 506df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 507df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationStart(Animator animation) { 5083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 5098b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getString(R.string.folder_closed)); 510df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_ANIMATING; 511df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 512df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen }); 5132801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.setDuration(mExpandDuration); 5140121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_HARDWARE, null); 515f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka oa.start(); 516df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 517df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 518cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen public boolean acceptDrop(DragObject d) { 519cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen final ItemInfo item = (ItemInfo) d.dragInfo; 520df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen final int itemType = item.itemType; 5212801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || 5222801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) && 5232801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen !isFull()); 524df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 525df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 526df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen protected boolean findAndSetEmptyCells(ShortcutInfo item) { 527df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen int[] emptyCell = new int[2]; 528df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) { 529df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen item.cellX = emptyCell[0]; 530df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen item.cellY = emptyCell[1]; 531df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return true; 532df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } else { 533df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return false; 534df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 535df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 536df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 537c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen protected boolean createAndAddShortcut(ShortcutInfo item) { 538df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen final TextView textView = 539e87b924efaaf1cfb555a4327dc653929a4c182f1Adam Cohen (TextView) mInflater.inflate(R.layout.application, this, false); 540df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setCompoundDrawablesWithIntrinsicBounds(null, 541df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen new FastBitmapDrawable(item.getIcon(mIconCache)), null, null); 542df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setText(item.title); 543df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setTag(item); 544df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 545df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setOnClickListener(this); 546df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setOnLongClickListener(this); 547df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 548c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // We need to check here to verify that the given item's location isn't already occupied 5493bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen // by another item. 5500057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0 5510057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) { 5523bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen // This shouldn't happen, log it. 5533bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen Log.e(TAG, "Folder order not properly persisted during bind"); 554c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen if (!findAndSetEmptyCells(item)) { 555c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen return false; 556c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 557c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 558c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 559df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen CellLayout.LayoutParams lp = 560df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY); 561df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen boolean insert = false; 562ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen textView.setOnKeyListener(new FolderKeyEventListener()); 563df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true); 564c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen return true; 565df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 566df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 567cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen public void onDragEnter(DragObject d) { 568bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mPreviousTargetCell[0] = -1; 569bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mPreviousTargetCell[1] = -1; 570bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.cancelAlarm(); 571df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 572df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 573bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen OnAlarmListener mReorderAlarmListener = new OnAlarmListener() { 574bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAlarm(Alarm alarm) { 575bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen realTimeReorder(mEmptyCell, mTargetCell); 576bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 577bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen }; 578bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 579bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen boolean readingOrderGreaterThan(int[] v1, int[] v2) { 580bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) { 581bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return true; 582bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 583bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return false; 584bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 585df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 586df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 587bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private void realTimeReorder(int[] empty, int[] target) { 588bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen boolean wrap; 589bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int startX; 590bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int endX; 591bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int startY; 59276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen int delay = 0; 59376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen float delayAmount = 30; 594bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (readingOrderGreaterThan(target, empty)) { 595bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen wrap = empty[0] >= mContent.getCountX() - 1; 596bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startY = wrap ? empty[1] + 1 : empty[1]; 597bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int y = startY; y <= target[1]; y++) { 598bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startX = y == empty[1] ? empty[0] + 1 : 0; 599bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen endX = y < target[1] ? mContent.getCountX() - 1 : target[0]; 600bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int x = startX; x <= endX; x++) { 601bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen View v = mContent.getChildAt(x,y); 602bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mContent.animateChildToPosition(v, empty[0], empty[1], 603482ed823afb4c7452e037ce8add7ea425fc83da2Adam Cohen REORDER_ANIMATION_DURATION, delay, true, true)) { 604bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[0] = x; 605bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[1] = y; 60676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delay += delayAmount; 60776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delayAmount *= 0.9; 608bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 609bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 610bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 611bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 612bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen wrap = empty[0] == 0; 613bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startY = wrap ? empty[1] - 1 : empty[1]; 614bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int y = startY; y >= target[1]; y--) { 615bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1; 616bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen endX = y > target[1] ? 0 : target[0]; 617bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int x = startX; x >= endX; x--) { 618bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen View v = mContent.getChildAt(x,y); 619bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mContent.animateChildToPosition(v, empty[0], empty[1], 620482ed823afb4c7452e037ce8add7ea425fc83da2Adam Cohen REORDER_ANIMATION_DURATION, delay, true, true)) { 621bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[0] = x; 622bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[1] = y; 62376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delay += delayAmount; 62476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delayAmount *= 0.9; 625bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 626bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 627bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 628bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 629bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 630bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 6312374abfda3e53f84e005df8923170308e4df8c03Adam Cohen public boolean isLayoutRtl() { 6322374abfda3e53f84e005df8923170308e4df8c03Adam Cohen return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 6332374abfda3e53f84e005df8923170308e4df8c03Adam Cohen } 6342374abfda3e53f84e005df8923170308e4df8c03Adam Cohen 63553b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini private Rect getDragObjectDrawingRect(View dragView, float[] r) { 63653b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini final Rect drawingRect = mTempRect; 63753b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini drawingRect.left = (int) r[0]; 63853b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini drawingRect.top = (int) r[1]; 63953b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini drawingRect.right = drawingRect.left + dragView.getMeasuredWidth(); 64053b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini drawingRect.bottom = drawingRect.top + dragView.getMeasuredHeight(); 64153b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini return drawingRect; 64253b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini } 64353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini 644bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDragOver(DragObject d) { 645f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int scrollOffset = mScrollView.getScrollY(); 646bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, null); 647f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen r[0] -= getPaddingLeft(); 648f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen r[1] -= getPaddingTop(); 64953b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini if (!mAutoScroller.onTouch(this, getDragObjectDrawingRect(d.dragView, r))) { 65053b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1] + scrollOffset, 1, 1, 65153b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mTargetCell); 652f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 65353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini if (isLayoutRtl()) { 65453b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mTargetCell[0] = mContent.getCountX() - mTargetCell[0] - 1; 655f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 65653b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini if (mTargetCell[0] != mPreviousTargetCell[0] 65753b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini || mTargetCell[1] != mPreviousTargetCell[1]) { 65853b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mReorderAlarm.cancelAlarm(); 65953b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mReorderAlarm.setOnAlarmListener(mReorderAlarmListener); 66053b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mReorderAlarm.setAlarm(REORDER_DELAY); 66153b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mPreviousTargetCell[0] = mTargetCell[0]; 66253b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mPreviousTargetCell[1] = mTargetCell[1]; 66353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mDragMode = DRAG_MODE_REORDER; 66453b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini } else { 66553b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mDragMode = DRAG_MODE_NONE; 666f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 66761a9a5c359e3e14cb1beaf43dbdb54e00911fe80Adam Cohen } else { 66861a9a5c359e3e14cb1beaf43dbdb54e00911fe80Adam Cohen mReorderAlarm.cancelAlarm(); 669bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 670df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 671df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 672bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // This is used to compute the visual center of the dragView. The idea is that 673bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // the visual center represents the user's interpretation of where the item is, and hence 674bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // is the appropriate point to use when determining drop location. 675bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset, 676bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen DragView dragView, float[] recycle) { 677bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen float res[]; 678bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (recycle == null) { 679bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res = new float[2]; 680bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 681bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res = recycle; 682df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 6832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 684bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // These represent the visual top and left of drag view if a dragRect was provided. 685bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // If a dragRect was not provided, then they correspond to the actual view left and 686bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // top, as the dragRect is in that case taken to be the entire dragView. 687bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // R.dimen.dragViewOffsetY. 688bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int left = x - xOffset; 689bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int top = y - yOffset; 690bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 691bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // In order to find the visual center, we shift by half the dragRect 692bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res[0] = left + dragView.getDragRegion().width() / 2; 693bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res[1] = top + dragView.getDragRegion().height() / 2; 694bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 695bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return res; 696bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 697bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 698bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() { 699bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAlarm(Alarm alarm) { 7003e8f811f31a2275e778244427271f77f4116c08bAdam Cohen completeDragExit(); 701bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 702bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen }; 7032801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 70495bb800de9b0142bea0110b074eddbcf0e475736Adam Cohen public void completeDragExit() { 7053e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mLauncher.closeFolder(); 7063e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mCurrentDragInfo = null; 7073e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mCurrentDragView = null; 7083e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mSuppressOnAdd = false; 7093e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mRearrangeOnClose = true; 7103e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 7113e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 712bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDragExit(DragObject d) { 71353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini // Exiting folder; stop the auto scroller. 71453b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mAutoScroller.stop(); 71553b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini // We only close the folder if this is a true drag exit, ie. not because 71653b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini // a drop has occurred above the folder. 717bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (!d.dragComplete) { 718bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener); 719bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY); 720bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 721bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mReorderAlarm.cancelAlarm(); 722f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mDragMode = DRAG_MODE_NONE; 7232801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 7242801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 7251e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka public void onDropCompleted(final View target, final DragObject d, 7261e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka final boolean isFlingToDelete, final boolean success) { 7271e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka if (mDeferDropAfterUninstall) { 728f3007589e346df224d357b389069adfeb266545eMichael Jurka Log.d(TAG, "Deferred handling drop because waiting for uninstall."); 7291e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mDeferredAction = new Runnable() { 7301e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka public void run() { 7311e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka onDropCompleted(target, d, isFlingToDelete, success); 7321e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mDeferredAction = null; 7331e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 7341e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka }; 7351e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka return; 7361e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 7371e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka 7381e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka boolean beingCalledAfterUninstall = mDeferredAction != null; 7391e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka boolean successfulDrop = 7401e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka success && (!beingCalledAfterUninstall || mUninstallSuccessful); 7415f8afe6280eae34620067696173e71943e1a30a3Winson Chung 7421e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka if (successfulDrop) { 74305e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) { 74467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen replaceFolderWithFinalItem(); 74567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 74667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } else { 7477a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen setupContentForNumItems(getItemCount()); 74867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen // The drag failed, we need to return the item to the folder 74967bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mFolderIcon.onDrop(d); 75067bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 75167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen 75267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (target != this) { 75367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (mOnExitAlarm.alarmPending()) { 75467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mOnExitAlarm.cancelAlarm(); 7555455425c1b0355f5dd652cc8e7a2369c33dc9883Michael Jurka if (!successfulDrop) { 7567a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen mSuppressFolderDeletion = true; 7577a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen } 75867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen completeDragExit(); 75967bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 76067bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 7615f8afe6280eae34620067696173e71943e1a30a3Winson Chung 76267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDeleteFolderOnDropCompleted = false; 76367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDragInProgress = false; 76405e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = false; 765bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragInfo = null; 766bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragView = null; 767bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mSuppressOnAdd = false; 7684045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen 7694045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen // Reordering may have occured, and we need to save the new item locations. We do this once 7704045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen // at the end to prevent unnecessary database operations. 771f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen updateItemLocationsInDatabaseBatch(); 7724045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen } 7734045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen 7741e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka public void deferCompleteDropAfterUninstallActivity() { 7751e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mDeferDropAfterUninstall = true; 7761e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 7771e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka 7781e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka public void onUninstallActivityReturned(boolean success) { 7791e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mDeferDropAfterUninstall = false; 7801e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mUninstallSuccessful = success; 7811e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka if (mDeferredAction != null) { 7821e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka mDeferredAction.run(); 7831e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 7841e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka } 7851e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka 786a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung @Override 787043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public boolean supportsFlingToDelete() { 788043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return true; 789043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 790043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 791a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung public void onFlingToDelete(DragObject d, int x, int y, PointF vec) { 792a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // Do nothing 793a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 794a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 795a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung @Override 796a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung public void onFlingToDeleteCompleted() { 797a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // Do nothing 798a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 799a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 8004045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen private void updateItemLocationsInDatabase() { 8014045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen ArrayList<View> list = getItemsInReadingOrder(); 8024045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen for (int i = 0; i < list.size(); i++) { 8034045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen View v = list.get(i); 8044045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen ItemInfo info = (ItemInfo) v.getTag(); 8054045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0, 8064045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen info.cellX, info.cellY); 8074045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen } 80867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 809228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 810f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private void updateItemLocationsInDatabaseBatch() { 811f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen ArrayList<View> list = getItemsInReadingOrder(); 812f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen ArrayList<ItemInfo> items = new ArrayList<ItemInfo>(); 813f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen for (int i = 0; i < list.size(); i++) { 814f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen View v = list.get(i); 815f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen ItemInfo info = (ItemInfo) v.getTag(); 816f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen items.add(info); 817f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 818f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 819f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen LauncherModel.moveItemsInDatabase(mLauncher, items, mInfo.id, 0); 820f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 821f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 822e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen public void addItemLocationsInDatabase() { 823e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen ArrayList<View> list = getItemsInReadingOrder(); 824e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen for (int i = 0; i < list.size(); i++) { 825e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen View v = list.get(i); 826e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen ItemInfo info = (ItemInfo) v.getTag(); 827e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen LauncherModel.addItemToDatabase(mLauncher, info, mInfo.id, 0, 828e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen info.cellX, info.cellY, false); 829e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen } 830e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen } 831e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen 83267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen public void notifyDrop() { 83367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (mDragInProgress) { 83405e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = true; 83576078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 836df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 837df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 838df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public boolean isDropEnabled() { 839df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return true; 840df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 841df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 8424045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen private void setupContentDimensions(int count) { 8432801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen ArrayList<View> list = getItemsInReadingOrder(); 8442801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8452801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int countX = mContent.getCountX(); 8462801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int countY = mContent.getCountY(); 8477c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen boolean done = false; 8487c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen 8497c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen while (!done) { 8507c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen int oldCountX = countX; 8517c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen int oldCountY = countY; 8527c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (countX * countY < count) { 8537c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen // Current grid is too small, expand it 85478dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) { 8557c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countX++; 8567c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if (countY < mMaxCountY) { 8577c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countY++; 8587c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 8597c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (countY == 0) countY++; 8607c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if ((countY - 1) * countX >= count && countY >= countX) { 8617c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countY = Math.max(0, countY - 1); 8627c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if ((countX - 1) * countY >= count) { 8637c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countX = Math.max(0, countX - 1); 8642801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8657c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen done = countX == oldCountX && countY == oldCountY; 8662801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8677c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mContent.setGridSize(countX, countY); 8682801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen arrangeChildren(list); 8692801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8702801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8712801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen public boolean isFull() { 87278dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen return getItemCount() >= mMaxNumItems; 8732801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8742801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8752801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void centerAboutIcon() { 8768e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); 8772801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8782801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); 879f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int height = getFolderHeight(); 8808e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer parent = (DragLayer) mLauncher.findViewById(R.id.drag_layer); 8818e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen 882307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect); 8832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 884307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen int centerX = (int) (mTempRect.left + mTempRect.width() * scale / 2); 885307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen int centerY = (int) (mTempRect.top + mTempRect.height() * scale / 2); 8862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int centeredLeft = centerX - width / 2; 8872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int centeredTop = centerY - height / 2; 8882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8897cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen int currentPage = mLauncher.getWorkspace().getCurrentPage(); 8907cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // In case the workspace is scrolling, we need to use the final scroll to compute 8917cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // the folders bounds. 8927cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen mLauncher.getWorkspace().setFinalScrollForPageChange(currentPage); 89335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // We first fetch the currently visible CellLayoutChildren 8947cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen CellLayout currentLayout = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPage); 895a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer boundingLayout = currentLayout.getShortcutsAndWidgets(); 89635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen Rect bounds = new Rect(); 89735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen parent.getDescendantRectRelativeToSelf(boundingLayout, bounds); 8987cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // We reset the workspaces scroll 8997cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen mLauncher.getWorkspace().resetFinalScrollForPageChange(currentPage); 90035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen 90135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // We need to bound the folder to the currently visible CellLayoutChildren 90235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen int left = Math.min(Math.max(bounds.left, centeredLeft), 90335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen bounds.left + bounds.width() - width); 90435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen int top = Math.min(Math.max(bounds.top, centeredTop), 90535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen bounds.top + bounds.height() - height); 90635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // If the folder doesn't fit within the bounds, center it about the desired bounds 90735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen if (width >= bounds.width()) { 90835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen left = bounds.left + (bounds.width() - width) / 2; 90935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen } 91035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen if (height >= bounds.height()) { 91135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen top = bounds.top + (bounds.height() - height) / 2; 9120e4857c302da6adbd45231d7a8bae0289fa33250Adam Cohen } 9132801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 9142801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int folderPivotX = width / 2 + (centeredLeft - left); 9152801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int folderPivotY = height / 2 + (centeredTop - top); 9162801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setPivotX(folderPivotX); 9172801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setPivotY(folderPivotY); 918268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen mFolderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() * 9192801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen (1.0f * folderPivotX / width)); 920268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen mFolderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() * 9212801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen (1.0f * folderPivotY / height)); 9223bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 923662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.width = width; 924662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.height = height; 925662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.x = left; 926662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.y = top; 9272801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9282801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 929268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen float getPivotXForIconAnimation() { 930268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen return mFolderIconPivotX; 931268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen } 932268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen float getPivotYForIconAnimation() { 933268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen return mFolderIconPivotY; 934268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen } 935268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen 9362801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void setupContentForNumItems(int count) { 9374045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen setupContentDimensions(count); 9382801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 9398e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); 9402801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (lp == null) { 9418e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen lp = new DragLayer.LayoutParams(0, 0); 9428e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen lp.customPosition = true; 9432801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setLayoutParams(lp); 9442801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9452801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen centerAboutIcon(); 9462801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9472801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 948f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private int getFolderHeight() { 949f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int contentAreaHeight = mContent.getDesiredHeight(); 950f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (contentAreaHeight >= mMaxContentAreaHeight) { 951f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen // Subtract a bit so the user can see that it's scrollable. 952f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen contentAreaHeight = mMaxContentAreaHeight; 953f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 954f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int height = getPaddingTop() + getPaddingBottom() + contentAreaHeight 955f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen + mFolderNameHeight; 956f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen return height; 957f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 958f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 959f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 960f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int contentAreaHeight = mContent.getDesiredHeight(); 961f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (contentAreaHeight >= mMaxContentAreaHeight) { 962f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen // Subtract a bit so the user can see that it's scrollable. 963f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen contentAreaHeight = mMaxContentAreaHeight; 964f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 965f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 966f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); 967f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int height = getFolderHeight(); 968f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(), 969234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.EXACTLY); 970f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(contentAreaHeight, 971234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.EXACTLY); 972234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen 973f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mContent.setFixedSize(mContent.getDesiredWidth(), mContent.getDesiredHeight()); 974f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec); 975f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mFolderName.measure(contentAreaWidthSpec, 976234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY)); 977234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen setMeasuredDimension(width, height); 978234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen } 979234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen 9802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void arrangeChildren(ArrayList<View> list) { 9812801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int[] vacant = new int[2]; 9822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (list == null) { 9832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen list = getItemsInReadingOrder(); 9842801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9852801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.removeAllViews(); 9862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 9872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen for (int i = 0; i < list.size(); i++) { 9882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen View v = list.get(i); 9892801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.getVacantCell(vacant, 1, 1); 9902801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams(); 9912801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen lp.cellX = vacant[0]; 9922801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen lp.cellY = vacant[1]; 9932801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen ItemInfo info = (ItemInfo) v.getTag(); 9942792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen if (info.cellX != vacant[0] || info.cellY != vacant[1]) { 9952792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellX = vacant[0]; 9962792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellY = vacant[1]; 9972792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0, 9982792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellX, info.cellY); 9992792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen } 10002801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen boolean insert = false; 10012801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true); 10022801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 10037c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = true; 10042801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 10052801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 1006a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public int getItemCount() { 1007a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka return mContent.getShortcutsAndWidgets().getChildCount(); 1008a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 1009a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 1010a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public View getItemAt(int index) { 1011a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka return mContent.getShortcutsAndWidgets().getChildAt(index); 1012a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 1013a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 10142801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void onCloseComplete() { 101505e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen DragLayer parent = (DragLayer) getParent(); 10165649c287039ea7908112b41604c3fc2893c4697eMichael Jurka if (parent != null) { 10175649c287039ea7908112b41604c3fc2893c4697eMichael Jurka parent.removeView(this); 10185649c287039ea7908112b41604c3fc2893c4697eMichael Jurka } 10194554ee16f122a3dbd9a8d3b828f1c8c7e7b7fe99Adam Cohen mDragController.removeDropTarget((DropTarget) this); 102005e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen clearFocus(); 1021ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderIcon.requestFocus(); 102205e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen 10232801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (mRearrangeOnClose) { 10242801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setupContentForNumItems(getItemCount()); 10252801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mRearrangeOnClose = false; 10262801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1027afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (getItemCount() <= 1) { 102867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (!mDragInProgress && !mSuppressFolderDeletion) { 102967bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen replaceFolderWithFinalItem(); 103067bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } else if (mDragInProgress) { 103167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDeleteFolderOnDropCompleted = true; 103267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 1033afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 103467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mSuppressFolderDeletion = false; 1035afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 1036afb01ee74243cede19088e694ca82cea5983c603Adam Cohen 1037afb01ee74243cede19088e694ca82cea5983c603Adam Cohen private void replaceFolderWithFinalItem() { 1038fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // Add the last remaining child to the workspace in place of the folder 1039fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen Runnable onCompleteRunnable = new Runnable() { 1040fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen @Override 1041fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen public void run() { 1042dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screenId); 1043fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 1044c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen View child = null; 1045fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // Move the item from the folder to the workspace, in the position of the folder 1046fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (getItemCount() == 1) { 1047fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen ShortcutInfo finalItem = mInfo.contents.get(0); 1048c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen child = mLauncher.createShortcut(R.layout.application, cellLayout, 1049fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen finalItem); 1050fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container, 1051dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen mInfo.screenId, mInfo.cellX, mInfo.cellY); 1052fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 1053487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen if (getItemCount() <= 1) { 1054487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen // Remove the folder 1055487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen LauncherModel.deleteItemFromDatabase(mLauncher, mInfo); 1056487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen cellLayout.removeView(mFolderIcon); 1057487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen if (mFolderIcon instanceof DropTarget) { 1058487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen mDragController.removeDropTarget((DropTarget) mFolderIcon); 1059487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen } 1060487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen mLauncher.removeFolder(mInfo); 1061487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen } 1062c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen // We add the child after removing the folder to prevent both from existing at 1063c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen // the same time in the CellLayout. 1064c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen if (child != null) { 1065dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screenId, 1066c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY); 1067c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen } 1068fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 1069fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen }; 1070fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen View finalChild = getItemAt(0); 1071fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (finalChild != null) { 1072fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable); 1073afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 1074fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mDestroyed = true; 1075fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 1076afb01ee74243cede19088e694ca82cea5983c603Adam Cohen 1077fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen boolean isDestroyed() { 1078fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen return mDestroyed; 10792801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 10802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 1081ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // This method keeps track of the last item in the folder for the purposes 1082ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // of keyboard focus 1083ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private void updateTextViewFocus() { 1084ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View lastChild = getItemAt(getItemCount() - 1); 1085ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen getItemAt(getItemCount() - 1); 1086ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (lastChild != null) { 1087ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusDownId(lastChild.getId()); 1088ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusRightId(lastChild.getId()); 1089ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusLeftId(lastChild.getId()); 1090ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusUpId(lastChild.getId()); 1091ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 1092ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 1093ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 1094bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDrop(DragObject d) { 1095bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen ShortcutInfo item; 1096bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (d.dragInfo instanceof ApplicationInfo) { 1097bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // Came from all apps -- make a copy 1098bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item = ((ApplicationInfo) d.dragInfo).makeShortcut(); 1099bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item.spanX = 1; 1100bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item.spanY = 1; 1101bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 1102bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item = (ShortcutInfo) d.dragInfo; 1103bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 110405e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // Dragged from self onto self, currently this is the only path possible, however 110505e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // we keep this as a distinct code path. 1106bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (item == mCurrentDragInfo) { 1107bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag(); 1108bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams(); 1109bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen si.cellX = lp.cellX = mEmptyCell[0]; 1110bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen si.cellX = lp.cellY = mEmptyCell[1]; 1111bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true); 1112fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen if (d.dragView.hasDrawn()) { 1113fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView); 1114fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen } else { 11152c4cf411f6c30fb2bfb47d2b13b680bda7a266dcWinson Chung d.deferDragViewCleanupPostAnimation = false; 1116fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mCurrentDragView.setVisibility(VISIBLE); 1117fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen } 1118e9166b247addcf67542ababb9d453f5bfb33c7b2Adam Cohen mItemsInvalidated = true; 11194045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen setupContentDimensions(getItemCount()); 1120716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mSuppressOnAdd = true; 1121bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1122bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mInfo.add(item); 1123bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1124bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 11257a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen // This is used so the item doesn't immediately appear in the folder when added. In one case 11267a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen // we need to create the illusion that the item isn't added back to the folder yet, to 11277a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen // to correspond to the animation of the icon back into the folder. This is 11287a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen public void hideItem(ShortcutInfo info) { 11297a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen View v = getViewForInfo(info); 11307a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen v.setVisibility(INVISIBLE); 11317a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen } 11327a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen public void showItem(ShortcutInfo info) { 11337a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen View v = getViewForInfo(info); 11347a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen v.setVisibility(VISIBLE); 11357a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen } 11367a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen 1137bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAdd(ShortcutInfo item) { 1138bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mItemsInvalidated = true; 113905e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // If the item was dropped onto this open folder, we have done the work associated 114005e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // with adding the item to the folder, as indicated by mSuppressOnAdd being set 1141bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mSuppressOnAdd) return; 1142bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (!findAndSetEmptyCells(item)) { 1143bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // The current layout is full, can we expand it? 1144bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen setupContentForNumItems(getItemCount() + 1); 1145bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen findAndSetEmptyCells(item); 1146bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1147bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen createAndAddShortcut(item); 1148bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen LauncherModel.addOrMoveItemInDatabase( 1149bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mLauncher, item, mInfo.id, 0, item.cellX, item.cellY); 1150bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1151bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 1152a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public void onRemove(ShortcutInfo item) { 11537c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = true; 115405e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // If this item is being dragged from this open folder, we have already handled 115505e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // the work associated with removing the item, so we don't have to do anything here. 1156bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (item == mCurrentDragInfo) return; 1157df1e4e868a1970b756486dadd652651d40276d36Adam Cohen View v = getViewForInfo(item); 1158a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen mContent.removeView(v); 11592801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (mState == STATE_ANIMATING) { 11602801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mRearrangeOnClose = true; 11612801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } else { 11622801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setupContentForNumItems(getItemCount()); 11632801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1164afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (getItemCount() <= 1) { 1165afb01ee74243cede19088e694ca82cea5983c603Adam Cohen replaceFolderWithFinalItem(); 1166afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 1167a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 11687c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen 1169df1e4e868a1970b756486dadd652651d40276d36Adam Cohen private View getViewForInfo(ShortcutInfo item) { 1170df1e4e868a1970b756486dadd652651d40276d36Adam Cohen for (int j = 0; j < mContent.getCountY(); j++) { 1171df1e4e868a1970b756486dadd652651d40276d36Adam Cohen for (int i = 0; i < mContent.getCountX(); i++) { 1172df1e4e868a1970b756486dadd652651d40276d36Adam Cohen View v = mContent.getChildAt(i, j); 1173df1e4e868a1970b756486dadd652651d40276d36Adam Cohen if (v.getTag() == item) { 1174df1e4e868a1970b756486dadd652651d40276d36Adam Cohen return v; 1175df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1176df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1177df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1178df1e4e868a1970b756486dadd652651d40276d36Adam Cohen return null; 1179df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1180df1e4e868a1970b756486dadd652651d40276d36Adam Cohen 118176078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen public void onItemsChanged() { 1182ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen updateTextViewFocus(); 118376078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 1184ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 118576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void onTitleChanged(CharSequence title) { 118676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 118776078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen 11887c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen public ArrayList<View> getItemsInReadingOrder() { 11897c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (mItemsInvalidated) { 11907c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInReadingOrder.clear(); 11917c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen for (int j = 0; j < mContent.getCountY(); j++) { 11927c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen for (int i = 0; i < mContent.getCountX(); i++) { 11937c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen View v = mContent.getChildAt(i, j); 11947c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (v != null) { 11957a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen mItemsInReadingOrder.add(v); 11967c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11977c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11987c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11997c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = false; 12007c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 12017c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen return mItemsInReadingOrder; 12027c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 12038dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen 12048dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void getLocationInDragLayer(int[] loc) { 12058dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mLauncher.getDragLayer().getLocationInDragLayer(this, loc); 12068dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 1207ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen 1208ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen public void onFocusChange(View v, boolean hasFocus) { 1209ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen if (v == mFolderName && hasFocus) { 1210ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen startEditingFolderName(); 1211ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen } 1212ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen } 12137d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen 12147d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen @Override 12157d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen public void getHitRectRelativeToDragLayer(Rect outRect) { 12167d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen getHitRect(outRect); 12177d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen } 121831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 1219