Folder.java revision 7d30a37007bac318db1c9af47a9af12d348042a5
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 12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Used to inflate the Workspace from XML. 13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param context The application's context. 13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param attrs The attribtues set containing the Workspace's customization values. 13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public Folder(Context context, AttributeSet attrs) { 13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, attrs); 13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project setAlwaysDrawnWithCacheEnabled(false); 138df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mInflater = LayoutInflater.from(context); 139cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler mIconCache = (LauncherAppState.getInstance()).getIconCache(); 14078dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen 14178dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen Resources res = getResources(); 142f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxCountX = mMaxVisibleX = res.getInteger(R.integer.folder_max_count_x); 143f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxCountY = mMaxVisibleY = res.getInteger(R.integer.folder_max_count_y); 14478dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen mMaxNumItems = res.getInteger(R.integer.folder_max_num_items); 145f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 146f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (mMaxCountY == -1) { 147f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen // -2 indicates unlimited 148f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxCountY = Integer.MAX_VALUE; 149f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxVisibleX = LauncherModel.getCellCountX() + 1; 150f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 151f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (mMaxNumItems == -1) { 152f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen // -2 indicates unlimited 153f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxNumItems = Integer.MAX_VALUE; 154f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxVisibleY = LauncherModel.getCellCountY() + 1; 155f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 156f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (mMaxCountX == 0) { 157f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxCountX = mMaxVisibleX = LauncherModel.getCellCountX(); 158f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxVisibleX++; 159f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 160f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (mMaxCountY == 0) { 161f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxCountY = mMaxVisibleY = LauncherModel.getCellCountY(); 162f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxVisibleY++; 163f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 164f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (mMaxNumItems == 0) { 16578dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen mMaxNumItems = mMaxCountX * mMaxCountY; 166f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (mMaxNumItems < 0) { 167f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxNumItems = Integer.MAX_VALUE; 168f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 16978dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen } 17076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 17176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mInputMethodManager = (InputMethodManager) 1728b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 17376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 17476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mExpandDuration = res.getInteger(R.integer.config_folderAnimDuration); 1754ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen 1764ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen if (sDefaultFolderName == null) { 1774ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen sDefaultFolderName = res.getString(R.string.folder_name); 1784ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } 179a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen if (sHintText == null) { 180a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen sHintText = res.getString(R.string.folder_hint_text); 181a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen } 1824eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen mLauncher = (Launcher) context; 183ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // We need this view to be focusable in touch mode so that when text editing of the folder 184ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // name is complete, we have something to focus on, thus hiding the cursor and giving 185ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // reliable behvior when clicking the text field (since it will always gain focus on click). 186ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen setFocusableInTouchMode(true); 18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected void onFinishInflate() { 19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super.onFinishInflate(); 192f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mScrollView = (ScrollView) findViewById(R.id.scroll_view); 193df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mContent = (CellLayout) findViewById(R.id.folder_content); 194f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 195f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen // Beyond this height, the area scrolls 196f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mContent.setGridSize(mMaxVisibleX, mMaxVisibleY); 197f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mMaxContentAreaHeight = mContent.getDesiredHeight() - SCROLL_CUT_OFF_AMOUNT; 198f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 1992801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.setGridSize(0, 0); 200a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false); 2012374abfda3e53f84e005df8923170308e4df8c03Adam Cohen mContent.setInvertIfRtl(true); 202ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName = (FolderEditText) findViewById(R.id.folder_name); 203ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setFolder(this); 204ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen mFolderName.setOnFocusChangeListener(this); 20576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 20676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // We find out how tall the text view wants to be (it is set to wrap_content), so that 20776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // we can allocate the appropriate amount of space for it. 20876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen int measureSpec = MeasureSpec.UNSPECIFIED; 20976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.measure(measureSpec, measureSpec); 21076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderNameHeight = mFolderName.getMeasuredHeight(); 21176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 21276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // We disable action mode for now since it messes up the view on phones 21376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback); 21476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.setOnEditorActionListener(this); 2154ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setSelectAllOnFocus(true); 2167a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohen mFolderName.setInputType(mFolderName.getInputType() | 2177a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohen InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS); 21853b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mAutoScroller = new AutoScroller(mScrollView); 21953b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mAutoScroller.setMaximumVelocityAbsolute(MAX_SCROLL_VELOCITY, MAX_SCROLL_VELOCITY); 22053b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mAutoScroller.setExtendsBeyondEdges(false); 22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 2222801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 22376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { 22476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 22576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 22676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 22776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 22876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onCreateActionMode(ActionMode mode, Menu menu) { 22976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 23076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 23176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 23276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void onDestroyActionMode(ActionMode mode) { 23376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 23476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 23576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 23676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 23776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 23876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen }; 23976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void onClick(View v) { 241df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen Object tag = v.getTag(); 242df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (tag instanceof ShortcutInfo) { 243b5fe60c8a502fb7e265e3183550478b2b2a49264Adam Cohen mLauncher.onClick(v); 244df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean onLongClick(View v) { 24836a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung // Return if global dragging is not enabled 24936a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung if (!mLauncher.isDraggingEnabled()) return true; 25036a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung 251df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen Object tag = v.getTag(); 252df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (tag instanceof ShortcutInfo) { 253df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ShortcutInfo item = (ShortcutInfo) tag; 254df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (!v.isInTouchMode()) { 255df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return false; 256df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 257df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 2587d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung mLauncher.dismissFolderCling(null); 2597d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung 260df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mLauncher.getWorkspace().onDragStartedWithItem(v); 261ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen mLauncher.getWorkspace().beginDragShared(v, this); 262badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen mIconDrawable = ((TextView) v).getCompoundDrawables()[1]; 26376078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen 26476078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen mCurrentDragInfo = item; 265bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mEmptyCell[0] = item.cellX; 266bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mEmptyCell[1] = item.cellY; 267bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragView = v; 268fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen 269fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mContent.removeView(mCurrentDragView); 270fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mInfo.remove(mCurrentDragInfo); 27167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDragInProgress = true; 27205e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = false; 273df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return true; 27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 27776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean isEditingName() { 27876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return mIsEditingName; 27976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 28076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 28176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void startEditingFolderName() { 282a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen mFolderName.setHint(""); 28376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mIsEditingName = true; 28476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 28576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 28676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void dismissEditingName() { 28776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 28876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen doneEditingFolderName(true); 28976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 29076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 29176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void doneEditingFolderName(boolean commit) { 292a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen mFolderName.setHint(sHintText); 2931df26a368a135395b7bd61e9b109044b33b1b0beAdam Cohen // Convert to a string here to ensure that no other state associated with the text field 2941df26a368a135395b7bd61e9b109044b33b1b0beAdam Cohen // gets saved. 2953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen String newTitle = mFolderName.getText().toString(); 2963371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mInfo.setTitle(newTitle); 29776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen LauncherModel.updateItemInDatabase(mLauncher, mInfo); 298ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 2993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (commit) { 3003371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 3018b805b17158886035b38261eb611d8641701ae43Michael Jurka String.format(getContext().getString(R.string.folder_renamed), newTitle)); 3023371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 303ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // In order to clear the focus from the text field, we set the focus on ourself. This 304ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // ensures that every time the field is clicked, focus is gained, giving reliable behavior. 305ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen requestFocus(); 306ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 307e601a43345224e3e386abc68bbea8b08b2df9570Adam Cohen Selection.setSelection((Spannable) mFolderName.getText(), 0, 0); 30876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mIsEditingName = false; 30976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 31076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 31176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 31276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen if (actionId == EditorInfo.IME_ACTION_DONE) { 31376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen dismissEditingName(); 31476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return true; 31576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 31676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 31776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 31876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 31976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public View getEditTextRegion() { 32076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return mFolderName; 32176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 32276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 323badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen public Drawable getDragDrawable() { 324badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen return mIconDrawable; 325badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen } 326badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 3270c872ba544ecfd9b106bb66137da8680927590deAdam Cohen /** 3280c872ba544ecfd9b106bb66137da8680927590deAdam Cohen * We need to handle touch events to prevent them from falling through to the workspace below. 3290c872ba544ecfd9b106bb66137da8680927590deAdam Cohen */ 3300c872ba544ecfd9b106bb66137da8680927590deAdam Cohen @Override 3310c872ba544ecfd9b106bb66137da8680927590deAdam Cohen public boolean onTouchEvent(MotionEvent ev) { 3320c872ba544ecfd9b106bb66137da8680927590deAdam Cohen return true; 3330c872ba544ecfd9b106bb66137da8680927590deAdam Cohen } 3340c872ba544ecfd9b106bb66137da8680927590deAdam Cohen 33500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void setDragController(DragController dragController) { 33600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragController = dragController; 33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3392801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen void setFolderIcon(FolderIcon icon) { 3402801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mFolderIcon = icon; 3412801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 3422801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 3433371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen @Override 3443371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 3453371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen // When the folder gets focus, we don't want to announce the list of items. 3463371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 3473371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 3483371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 35031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @return the FolderInfo object associated with this folder 35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project FolderInfo getInfo() { 35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return mInfo; 35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3563bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen private class GridComparator implements Comparator<ShortcutInfo> { 3573bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int mNumCols; 3583bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen public GridComparator(int numCols) { 3593bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen mNumCols = numCols; 3603bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3613bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 3623bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen @Override 3633bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen public int compare(ShortcutInfo lhs, ShortcutInfo rhs) { 3643bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int lhIndex = lhs.cellY * mNumCols + lhs.cellX; 3653bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int rhIndex = rhs.cellY * mNumCols + rhs.cellX; 3663bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen return (lhIndex - rhIndex); 3673bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3683bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3693bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 3703bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen private void placeInReadingOrder(ArrayList<ShortcutInfo> items) { 3713bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int maxX = 0; 3723bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int count = items.size(); 3733bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen for (int i = 0; i < count; i++) { 3743bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen ShortcutInfo item = items.get(i); 3753bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen if (item.cellX > maxX) { 3763bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen maxX = item.cellX; 3773bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3783bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 379691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen 380691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen GridComparator gridComparator = new GridComparator(maxX + 1); 3813bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen Collections.sort(items, gridComparator); 3823bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen final int countX = mContent.getCountX(); 3833bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen for (int i = 0; i < count; i++) { 3843bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int x = i % countX; 3853bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int y = i / countX; 3863bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen ShortcutInfo item = items.get(i); 3873bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen item.cellX = x; 3883bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen item.cellY = y; 3893bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3903bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3913bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 39231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project void bind(FolderInfo info) { 39331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mInfo = info; 394df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ArrayList<ShortcutInfo> children = info.contents; 395c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>(); 3967c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen setupContentForNumItems(children.size()); 3973bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen placeInReadingOrder(children); 3980057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen int count = 0; 399df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen for (int i = 0; i < children.size(); i++) { 400df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ShortcutInfo child = (ShortcutInfo) children.get(i); 401c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen if (!createAndAddShortcut(child)) { 402c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen overflow.add(child); 4030057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen } else { 4040057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen count++; 405c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 406df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 407c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 4080057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen // We rearrange the items in case there are any empty gaps 4090057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen setupContentForNumItems(count); 4100057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen 411c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // If our folder has too many items we prune them from the list. This is an issue 412c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // when upgrading from the old Folders implementation which could contain an unlimited 413c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // number of items. 414c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen for (ShortcutInfo item: overflow) { 415c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen mInfo.remove(item); 416c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen LauncherModel.deleteItemFromDatabase(mLauncher, item); 417c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 418c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 4194dbe6d993485a702505ee4895db94aaa89655f2cAdam Cohen mItemsInvalidated = true; 420ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen updateTextViewFocus(); 421a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen mInfo.addListener(this); 4224ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen 423afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (!sDefaultFolderName.contentEquals(mInfo.title)) { 4244ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setText(mInfo.title); 4254ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } else { 4264ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setText(""); 4274ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } 428691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen updateItemLocationsInDatabase(); 429df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 430df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 431df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen /** 432df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * Creates a new UserFolder, inflated from R.layout.user_folder. 433df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * 434df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * @param context The application's context. 435df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * 436df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * @return A new UserFolder. 437df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen */ 438df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static Folder fromXml(Context context) { 439df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null); 440df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 441df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 442df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen /** 443df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * This method is intended to make the UserFolder to be visually identical in size and position 444df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * to its associated FolderIcon. This allows for a seamless transition into the expanded state. 445df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen */ 446df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private void positionAndSizeAsIcon() { 4473e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (!(getParent() instanceof DragLayer)) return; 448662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setScaleX(0.8f); 449662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setScaleY(0.8f); 450662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setAlpha(0f); 451df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_SMALL; 452df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 453df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 454df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void animateOpen() { 4553e8f811f31a2275e778244427271f77f4116c08bAdam Cohen positionAndSizeAsIcon(); 4563e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 4578e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen if (!(getParent() instanceof DragLayer)) return; 4582801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen centerAboutIcon(); 459662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1); 460662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f); 461662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f); 462032e6bad1ba588ed8a884fb8f28fb8596efac480Michael Jurka final ObjectAnimator oa = 4632ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); 4646441de0ec2a71862798dd51180d0811b42edd514Adam Cohen 4652801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.addListener(new AnimatorListenerAdapter() { 466df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 467df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationStart(Animator animation) { 4683371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 4698b805b17158886035b38261eb611d8641701ae43Michael Jurka String.format(getContext().getString(R.string.folder_opened), 4703371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mContent.getCountX(), mContent.getCountY())); 471df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_ANIMATING; 472df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 473df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 474df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationEnd(Animator animation) { 4752801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mState = STATE_OPEN; 4760121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_NONE, null); 4777a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung Cling cling = mLauncher.showFirstRunFoldersCling(); 4787a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung if (cling != null) { 4797a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung cling.bringToFront(); 4807a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung } 481ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen setFocusOnFirstChild(); 482df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 483df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen }); 4842801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.setDuration(mExpandDuration); 4850121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_HARDWARE, null); 486f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka oa.start(); 487df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 488df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 4893371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private void sendCustomAccessibilityEvent(int type, String text) { 4908b805b17158886035b38261eb611d8641701ae43Michael Jurka AccessibilityManager accessibilityManager = (AccessibilityManager) 4918b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 4928b805b17158886035b38261eb611d8641701ae43Michael Jurka if (accessibilityManager.isEnabled()) { 4933371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen AccessibilityEvent event = AccessibilityEvent.obtain(type); 4943371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen onInitializeAccessibilityEvent(event); 4953371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen event.getText().add(text); 4968b805b17158886035b38261eb611d8641701ae43Michael Jurka accessibilityManager.sendAccessibilityEvent(event); 4973371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 4983371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 4993371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 500ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private void setFocusOnFirstChild() { 501ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View firstChild = mContent.getChildAt(0, 0); 502ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (firstChild != null) { 503ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen firstChild.requestFocus(); 504ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 505ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 506ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 507df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void animateClosed() { 5088e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen if (!(getParent() instanceof DragLayer)) return; 509662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0); 510662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f); 511662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f); 512032e6bad1ba588ed8a884fb8f28fb8596efac480Michael Jurka final ObjectAnimator oa = 5132ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); 514df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 5152801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.addListener(new AnimatorListenerAdapter() { 516df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 517df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationEnd(Animator animation) { 5182801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen onCloseComplete(); 5190121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_NONE, null); 5202801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mState = STATE_SMALL; 521df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 522df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 523df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationStart(Animator animation) { 5243371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 5258b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getString(R.string.folder_closed)); 526df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_ANIMATING; 527df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 528df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen }); 5292801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.setDuration(mExpandDuration); 5300121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_HARDWARE, null); 531f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka oa.start(); 532df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 533df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 534df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen void notifyDataSetChanged() { 535df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen // recreate all the children if the data set changes under us. We may want to do this more 536df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen // intelligently (ie just removing the views that should no longer exist) 537df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mContent.removeAllViewsInLayout(); 538df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen bind(mInfo); 539df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 540df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 541cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen public boolean acceptDrop(DragObject d) { 542cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen final ItemInfo item = (ItemInfo) d.dragInfo; 543df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen final int itemType = item.itemType; 5442801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || 5452801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) && 5462801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen !isFull()); 547df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 548df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 549df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen protected boolean findAndSetEmptyCells(ShortcutInfo item) { 550df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen int[] emptyCell = new int[2]; 551df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) { 552df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen item.cellX = emptyCell[0]; 553df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen item.cellY = emptyCell[1]; 554df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return true; 555df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } else { 556df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return false; 557df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 558df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 559df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 560c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen protected boolean createAndAddShortcut(ShortcutInfo item) { 561df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen final TextView textView = 562e87b924efaaf1cfb555a4327dc653929a4c182f1Adam Cohen (TextView) mInflater.inflate(R.layout.application, this, false); 563df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setCompoundDrawablesWithIntrinsicBounds(null, 564df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen new FastBitmapDrawable(item.getIcon(mIconCache)), null, null); 565df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setText(item.title); 566df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setTag(item); 567df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 568df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setOnClickListener(this); 569df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setOnLongClickListener(this); 570df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 571c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // We need to check here to verify that the given item's location isn't already occupied 5723bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen // by another item. 5730057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0 5740057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) { 5753bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen // This shouldn't happen, log it. 5763bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen Log.e(TAG, "Folder order not properly persisted during bind"); 577c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen if (!findAndSetEmptyCells(item)) { 578c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen return false; 579c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 580c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 581c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 582df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen CellLayout.LayoutParams lp = 583df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY); 584df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen boolean insert = false; 585ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen textView.setOnKeyListener(new FolderKeyEventListener()); 586df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true); 587c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen return true; 588df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 589df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 590cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen public void onDragEnter(DragObject d) { 591bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mPreviousTargetCell[0] = -1; 592bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mPreviousTargetCell[1] = -1; 593bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.cancelAlarm(); 594df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 595df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 596bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen OnAlarmListener mReorderAlarmListener = new OnAlarmListener() { 597bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAlarm(Alarm alarm) { 598bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen realTimeReorder(mEmptyCell, mTargetCell); 599bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 600bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen }; 601bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 602bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen boolean readingOrderGreaterThan(int[] v1, int[] v2) { 603bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) { 604bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return true; 605bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 606bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return false; 607bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 608df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 609df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 610bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private void realTimeReorder(int[] empty, int[] target) { 611bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen boolean wrap; 612bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int startX; 613bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int endX; 614bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int startY; 61576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen int delay = 0; 61676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen float delayAmount = 30; 617bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (readingOrderGreaterThan(target, empty)) { 618bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen wrap = empty[0] >= mContent.getCountX() - 1; 619bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startY = wrap ? empty[1] + 1 : empty[1]; 620bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int y = startY; y <= target[1]; y++) { 621bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startX = y == empty[1] ? empty[0] + 1 : 0; 622bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen endX = y < target[1] ? mContent.getCountX() - 1 : target[0]; 623bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int x = startX; x <= endX; x++) { 624bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen View v = mContent.getChildAt(x,y); 625bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mContent.animateChildToPosition(v, empty[0], empty[1], 626482ed823afb4c7452e037ce8add7ea425fc83da2Adam Cohen REORDER_ANIMATION_DURATION, delay, true, true)) { 627bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[0] = x; 628bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[1] = y; 62976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delay += delayAmount; 63076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delayAmount *= 0.9; 631bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 632bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 633bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 634bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 635bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen wrap = empty[0] == 0; 636bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startY = wrap ? empty[1] - 1 : empty[1]; 637bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int y = startY; y >= target[1]; y--) { 638bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1; 639bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen endX = y > target[1] ? 0 : target[0]; 640bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int x = startX; x >= endX; x--) { 641bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen View v = mContent.getChildAt(x,y); 642bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mContent.animateChildToPosition(v, empty[0], empty[1], 643482ed823afb4c7452e037ce8add7ea425fc83da2Adam Cohen REORDER_ANIMATION_DURATION, delay, true, true)) { 644bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[0] = x; 645bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[1] = y; 64676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delay += delayAmount; 64776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delayAmount *= 0.9; 648bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 649bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 650bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 651bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 652bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 653bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 6542374abfda3e53f84e005df8923170308e4df8c03Adam Cohen public boolean isLayoutRtl() { 6552374abfda3e53f84e005df8923170308e4df8c03Adam Cohen return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 6562374abfda3e53f84e005df8923170308e4df8c03Adam Cohen } 6572374abfda3e53f84e005df8923170308e4df8c03Adam Cohen 65853b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini private Rect getDragObjectDrawingRect(View dragView, float[] r) { 65953b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini final Rect drawingRect = mTempRect; 66053b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini drawingRect.left = (int) r[0]; 66153b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini drawingRect.top = (int) r[1]; 66253b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini drawingRect.right = drawingRect.left + dragView.getMeasuredWidth(); 66353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini drawingRect.bottom = drawingRect.top + dragView.getMeasuredHeight(); 66453b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini return drawingRect; 66553b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini } 66653b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini 667bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDragOver(DragObject d) { 668f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int scrollOffset = mScrollView.getScrollY(); 669bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, null); 670f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen r[0] -= getPaddingLeft(); 671f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen r[1] -= getPaddingTop(); 67253b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini if (!mAutoScroller.onTouch(this, getDragObjectDrawingRect(d.dragView, r))) { 67353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1] + scrollOffset, 1, 1, 67453b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mTargetCell); 675f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 67653b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini if (isLayoutRtl()) { 67753b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mTargetCell[0] = mContent.getCountX() - mTargetCell[0] - 1; 678f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 67953b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini if (mTargetCell[0] != mPreviousTargetCell[0] 68053b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini || mTargetCell[1] != mPreviousTargetCell[1]) { 68153b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mReorderAlarm.cancelAlarm(); 68253b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mReorderAlarm.setOnAlarmListener(mReorderAlarmListener); 68353b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mReorderAlarm.setAlarm(REORDER_DELAY); 68453b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mPreviousTargetCell[0] = mTargetCell[0]; 68553b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mPreviousTargetCell[1] = mTargetCell[1]; 68653b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mDragMode = DRAG_MODE_REORDER; 68753b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini } else { 68853b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mDragMode = DRAG_MODE_NONE; 689f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 690bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 691df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 692df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 693bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // This is used to compute the visual center of the dragView. The idea is that 694bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // the visual center represents the user's interpretation of where the item is, and hence 695bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // is the appropriate point to use when determining drop location. 696bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset, 697bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen DragView dragView, float[] recycle) { 698bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen float res[]; 699bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (recycle == null) { 700bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res = new float[2]; 701bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 702bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res = recycle; 703df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 7042801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 705bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // These represent the visual top and left of drag view if a dragRect was provided. 706bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // If a dragRect was not provided, then they correspond to the actual view left and 707bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // top, as the dragRect is in that case taken to be the entire dragView. 708bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // R.dimen.dragViewOffsetY. 709bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int left = x - xOffset; 710bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int top = y - yOffset; 711bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 712bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // In order to find the visual center, we shift by half the dragRect 713bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res[0] = left + dragView.getDragRegion().width() / 2; 714bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res[1] = top + dragView.getDragRegion().height() / 2; 715bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 716bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return res; 717bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 718bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 719bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() { 720bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAlarm(Alarm alarm) { 7213e8f811f31a2275e778244427271f77f4116c08bAdam Cohen completeDragExit(); 722bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 723bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen }; 7242801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 72595bb800de9b0142bea0110b074eddbcf0e475736Adam Cohen public void completeDragExit() { 7263e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mLauncher.closeFolder(); 7273e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mCurrentDragInfo = null; 7283e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mCurrentDragView = null; 7293e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mSuppressOnAdd = false; 7303e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mRearrangeOnClose = true; 7313e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 7323e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 733bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDragExit(DragObject d) { 73453b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini // Exiting folder; stop the auto scroller. 73553b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini mAutoScroller.stop(); 73653b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini // We only close the folder if this is a true drag exit, ie. not because 73753b8d071ce63b2b55fa8bdc71488c44308bfcf2fMindy DelliCarpini // a drop has occurred above the folder. 738bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (!d.dragComplete) { 739bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener); 740bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY); 741bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 742bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mReorderAlarm.cancelAlarm(); 743f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mDragMode = DRAG_MODE_NONE; 7442801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 7452801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 746a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete, 747a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung boolean success) { 74867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (success) { 74905e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) { 75067bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen replaceFolderWithFinalItem(); 75167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 75267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } else { 7537a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen setupContentForNumItems(getItemCount()); 75467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen // The drag failed, we need to return the item to the folder 75567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mFolderIcon.onDrop(d); 75667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 75767bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen 75867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (target != this) { 75967bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (mOnExitAlarm.alarmPending()) { 76067bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mOnExitAlarm.cancelAlarm(); 7617a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen if (!success) { 7627a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen mSuppressFolderDeletion = true; 7637a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen } 76467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen completeDragExit(); 76567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 76667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 76767bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDeleteFolderOnDropCompleted = false; 76867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDragInProgress = false; 76905e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = false; 770bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragInfo = null; 771bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragView = null; 772bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mSuppressOnAdd = false; 7734045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen 7744045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen // Reordering may have occured, and we need to save the new item locations. We do this once 7754045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen // at the end to prevent unnecessary database operations. 776f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen updateItemLocationsInDatabaseBatch(); 7774045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen } 7784045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen 779a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung @Override 780043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public boolean supportsFlingToDelete() { 781043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return true; 782043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 783043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 784a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung public void onFlingToDelete(DragObject d, int x, int y, PointF vec) { 785a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // Do nothing 786a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 787a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 788a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung @Override 789a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung public void onFlingToDeleteCompleted() { 790a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // Do nothing 791a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 792a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 7934045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen private void updateItemLocationsInDatabase() { 7944045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen ArrayList<View> list = getItemsInReadingOrder(); 7954045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen for (int i = 0; i < list.size(); i++) { 7964045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen View v = list.get(i); 7974045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen ItemInfo info = (ItemInfo) v.getTag(); 7984045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0, 7994045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen info.cellX, info.cellY); 8004045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen } 80167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 802228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 803f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private void updateItemLocationsInDatabaseBatch() { 804f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen ArrayList<View> list = getItemsInReadingOrder(); 805f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen ArrayList<ItemInfo> items = new ArrayList<ItemInfo>(); 806f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen for (int i = 0; i < list.size(); i++) { 807f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen View v = list.get(i); 808f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen ItemInfo info = (ItemInfo) v.getTag(); 809f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen items.add(info); 810f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 811f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 812f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen LauncherModel.moveItemsInDatabase(mLauncher, items, mInfo.id, 0); 813f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 814f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 815e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen public void addItemLocationsInDatabase() { 816e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen ArrayList<View> list = getItemsInReadingOrder(); 817e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen for (int i = 0; i < list.size(); i++) { 818e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen View v = list.get(i); 819e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen ItemInfo info = (ItemInfo) v.getTag(); 820e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen LauncherModel.addItemToDatabase(mLauncher, info, mInfo.id, 0, 821e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen info.cellX, info.cellY, false); 822e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen } 823e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen } 824e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen 82567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen public void notifyDrop() { 82667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (mDragInProgress) { 82705e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = true; 82876078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 829df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 830df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 831df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public boolean isDropEnabled() { 832df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return true; 833df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 834df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 8354045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen private void setupContentDimensions(int count) { 8362801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen ArrayList<View> list = getItemsInReadingOrder(); 8372801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8382801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int countX = mContent.getCountX(); 8392801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int countY = mContent.getCountY(); 8407c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen boolean done = false; 8417c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen 8427c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen while (!done) { 8437c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen int oldCountX = countX; 8447c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen int oldCountY = countY; 8457c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (countX * countY < count) { 8467c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen // Current grid is too small, expand it 84778dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) { 8487c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countX++; 8497c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if (countY < mMaxCountY) { 8507c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countY++; 8517c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 8527c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (countY == 0) countY++; 8537c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if ((countY - 1) * countX >= count && countY >= countX) { 8547c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countY = Math.max(0, countY - 1); 8557c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if ((countX - 1) * countY >= count) { 8567c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countX = Math.max(0, countX - 1); 8572801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8587c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen done = countX == oldCountX && countY == oldCountY; 8592801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8607c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mContent.setGridSize(countX, countY); 8612801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen arrangeChildren(list); 8622801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8632801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8642801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen public boolean isFull() { 86578dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen return getItemCount() >= mMaxNumItems; 8662801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8672801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8682801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void centerAboutIcon() { 8698e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); 8702801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8712801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); 872f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int height = getFolderHeight(); 8738e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer parent = (DragLayer) mLauncher.findViewById(R.id.drag_layer); 8748e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen 875307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect); 8762801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 877307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen int centerX = (int) (mTempRect.left + mTempRect.width() * scale / 2); 878307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen int centerY = (int) (mTempRect.top + mTempRect.height() * scale / 2); 8792801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int centeredLeft = centerX - width / 2; 8802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int centeredTop = centerY - height / 2; 8812801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8827cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen int currentPage = mLauncher.getWorkspace().getCurrentPage(); 8837cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // In case the workspace is scrolling, we need to use the final scroll to compute 8847cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // the folders bounds. 8857cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen mLauncher.getWorkspace().setFinalScrollForPageChange(currentPage); 88635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // We first fetch the currently visible CellLayoutChildren 8877cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen CellLayout currentLayout = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPage); 888a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer boundingLayout = currentLayout.getShortcutsAndWidgets(); 88935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen Rect bounds = new Rect(); 89035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen parent.getDescendantRectRelativeToSelf(boundingLayout, bounds); 8917cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // We reset the workspaces scroll 8927cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen mLauncher.getWorkspace().resetFinalScrollForPageChange(currentPage); 89335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen 89435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // We need to bound the folder to the currently visible CellLayoutChildren 89535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen int left = Math.min(Math.max(bounds.left, centeredLeft), 89635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen bounds.left + bounds.width() - width); 89735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen int top = Math.min(Math.max(bounds.top, centeredTop), 89835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen bounds.top + bounds.height() - height); 89935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // If the folder doesn't fit within the bounds, center it about the desired bounds 90035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen if (width >= bounds.width()) { 90135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen left = bounds.left + (bounds.width() - width) / 2; 90235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen } 90335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen if (height >= bounds.height()) { 90435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen top = bounds.top + (bounds.height() - height) / 2; 9050e4857c302da6adbd45231d7a8bae0289fa33250Adam Cohen } 9062801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 9072801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int folderPivotX = width / 2 + (centeredLeft - left); 9082801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int folderPivotY = height / 2 + (centeredTop - top); 9092801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setPivotX(folderPivotX); 9102801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setPivotY(folderPivotY); 911268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen mFolderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() * 9122801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen (1.0f * folderPivotX / width)); 913268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen mFolderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() * 9142801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen (1.0f * folderPivotY / height)); 9153bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 916662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.width = width; 917662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.height = height; 918662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.x = left; 919662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.y = top; 9202801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9212801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 922268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen float getPivotXForIconAnimation() { 923268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen return mFolderIconPivotX; 924268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen } 925268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen float getPivotYForIconAnimation() { 926268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen return mFolderIconPivotY; 927268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen } 928268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen 9292801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void setupContentForNumItems(int count) { 9304045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen setupContentDimensions(count); 9312801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 9328e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); 9332801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (lp == null) { 9348e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen lp = new DragLayer.LayoutParams(0, 0); 9358e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen lp.customPosition = true; 9362801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setLayoutParams(lp); 9372801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9382801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen centerAboutIcon(); 9392801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9402801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 941f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen private int getFolderHeight() { 942f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int contentAreaHeight = mContent.getDesiredHeight(); 943f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (contentAreaHeight >= mMaxContentAreaHeight) { 944f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen // Subtract a bit so the user can see that it's scrollable. 945f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen contentAreaHeight = mMaxContentAreaHeight; 946f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 947f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int height = getPaddingTop() + getPaddingBottom() + contentAreaHeight 948f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen + mFolderNameHeight; 949f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen return height; 950f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 951f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 952f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 953234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen 954f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int contentAreaHeight = mContent.getDesiredHeight(); 955f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen if (contentAreaHeight >= mMaxContentAreaHeight) { 956f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen // Subtract a bit so the user can see that it's scrollable. 957f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen contentAreaHeight = mMaxContentAreaHeight; 958f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen } 959f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen 960f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); 961f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int height = getFolderHeight(); 962f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(), 963234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.EXACTLY); 964f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(contentAreaHeight, 965234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.EXACTLY); 966234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen 967f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mContent.setFixedSize(mContent.getDesiredWidth(), mContent.getDesiredHeight()); 968f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec); 969f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen mFolderName.measure(contentAreaWidthSpec, 970234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY)); 971234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen setMeasuredDimension(width, height); 972234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen } 973234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen 9742801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void arrangeChildren(ArrayList<View> list) { 9752801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int[] vacant = new int[2]; 9762801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (list == null) { 9772801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen list = getItemsInReadingOrder(); 9782801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9792801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.removeAllViews(); 9802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 9812801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen for (int i = 0; i < list.size(); i++) { 9822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen View v = list.get(i); 9832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.getVacantCell(vacant, 1, 1); 9842801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams(); 9852801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen lp.cellX = vacant[0]; 9862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen lp.cellY = vacant[1]; 9872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen ItemInfo info = (ItemInfo) v.getTag(); 9882792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen if (info.cellX != vacant[0] || info.cellY != vacant[1]) { 9892792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellX = vacant[0]; 9902792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellY = vacant[1]; 9912792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0, 9922792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellX, info.cellY); 9932792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen } 9942801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen boolean insert = false; 9952801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true); 9962801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9977c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = true; 9982801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9992801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 1000a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public int getItemCount() { 1001a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka return mContent.getShortcutsAndWidgets().getChildCount(); 1002a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 1003a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 1004a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public View getItemAt(int index) { 1005a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka return mContent.getShortcutsAndWidgets().getChildAt(index); 1006a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 1007a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 10082801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void onCloseComplete() { 100905e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen DragLayer parent = (DragLayer) getParent(); 10105649c287039ea7908112b41604c3fc2893c4697eMichael Jurka if (parent != null) { 10115649c287039ea7908112b41604c3fc2893c4697eMichael Jurka parent.removeView(this); 10125649c287039ea7908112b41604c3fc2893c4697eMichael Jurka } 10134554ee16f122a3dbd9a8d3b828f1c8c7e7b7fe99Adam Cohen mDragController.removeDropTarget((DropTarget) this); 101405e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen clearFocus(); 1015ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderIcon.requestFocus(); 101605e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen 10172801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (mRearrangeOnClose) { 10182801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setupContentForNumItems(getItemCount()); 10192801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mRearrangeOnClose = false; 10202801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1021afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (getItemCount() <= 1) { 102267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (!mDragInProgress && !mSuppressFolderDeletion) { 102367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen replaceFolderWithFinalItem(); 102467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } else if (mDragInProgress) { 102567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDeleteFolderOnDropCompleted = true; 102667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 1027afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 102867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mSuppressFolderDeletion = false; 1029afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 1030afb01ee74243cede19088e694ca82cea5983c603Adam Cohen 1031afb01ee74243cede19088e694ca82cea5983c603Adam Cohen private void replaceFolderWithFinalItem() { 1032fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // Add the last remaining child to the workspace in place of the folder 1033fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen Runnable onCompleteRunnable = new Runnable() { 1034fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen @Override 1035fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen public void run() { 1036dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screenId); 1037fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 1038c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen View child = null; 1039fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // Move the item from the folder to the workspace, in the position of the folder 1040fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (getItemCount() == 1) { 1041fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen ShortcutInfo finalItem = mInfo.contents.get(0); 1042c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen child = mLauncher.createShortcut(R.layout.application, cellLayout, 1043fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen finalItem); 1044fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container, 1045dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen mInfo.screenId, mInfo.cellX, mInfo.cellY); 1046fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 1047487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen if (getItemCount() <= 1) { 1048487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen // Remove the folder 1049487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen LauncherModel.deleteItemFromDatabase(mLauncher, mInfo); 1050487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen cellLayout.removeView(mFolderIcon); 1051487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen if (mFolderIcon instanceof DropTarget) { 1052487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen mDragController.removeDropTarget((DropTarget) mFolderIcon); 1053487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen } 1054487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen mLauncher.removeFolder(mInfo); 1055487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen } 1056c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen // We add the child after removing the folder to prevent both from existing at 1057c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen // the same time in the CellLayout. 1058c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen if (child != null) { 1059dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screenId, 1060c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY); 1061c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen } 1062fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 1063fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen }; 1064fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen View finalChild = getItemAt(0); 1065fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (finalChild != null) { 1066fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable); 1067afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 1068fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mDestroyed = true; 1069fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 1070afb01ee74243cede19088e694ca82cea5983c603Adam Cohen 1071fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen boolean isDestroyed() { 1072fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen return mDestroyed; 10732801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 10742801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 1075ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // This method keeps track of the last item in the folder for the purposes 1076ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // of keyboard focus 1077ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private void updateTextViewFocus() { 1078ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View lastChild = getItemAt(getItemCount() - 1); 1079ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen getItemAt(getItemCount() - 1); 1080ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (lastChild != null) { 1081ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusDownId(lastChild.getId()); 1082ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusRightId(lastChild.getId()); 1083ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusLeftId(lastChild.getId()); 1084ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusUpId(lastChild.getId()); 1085ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 1086ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 1087ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 1088bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDrop(DragObject d) { 1089bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen ShortcutInfo item; 1090bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (d.dragInfo instanceof ApplicationInfo) { 1091bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // Came from all apps -- make a copy 1092bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item = ((ApplicationInfo) d.dragInfo).makeShortcut(); 1093bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item.spanX = 1; 1094bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item.spanY = 1; 1095bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 1096bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item = (ShortcutInfo) d.dragInfo; 1097bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 109805e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // Dragged from self onto self, currently this is the only path possible, however 109905e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // we keep this as a distinct code path. 1100bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (item == mCurrentDragInfo) { 1101bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag(); 1102bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams(); 1103bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen si.cellX = lp.cellX = mEmptyCell[0]; 1104bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen si.cellX = lp.cellY = mEmptyCell[1]; 1105bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true); 1106fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen if (d.dragView.hasDrawn()) { 1107fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView); 1108fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen } else { 11092c4cf411f6c30fb2bfb47d2b13b680bda7a266dcWinson Chung d.deferDragViewCleanupPostAnimation = false; 1110fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mCurrentDragView.setVisibility(VISIBLE); 1111fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen } 1112e9166b247addcf67542ababb9d453f5bfb33c7b2Adam Cohen mItemsInvalidated = true; 11134045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen setupContentDimensions(getItemCount()); 1114716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mSuppressOnAdd = true; 1115bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1116bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mInfo.add(item); 1117bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1118bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 11197a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen // This is used so the item doesn't immediately appear in the folder when added. In one case 11207a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen // we need to create the illusion that the item isn't added back to the folder yet, to 11217a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen // to correspond to the animation of the icon back into the folder. This is 11227a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen public void hideItem(ShortcutInfo info) { 11237a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen View v = getViewForInfo(info); 11247a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen v.setVisibility(INVISIBLE); 11257a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen } 11267a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen public void showItem(ShortcutInfo info) { 11277a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen View v = getViewForInfo(info); 11287a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen v.setVisibility(VISIBLE); 11297a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen } 11307a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen 1131bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAdd(ShortcutInfo item) { 1132bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mItemsInvalidated = true; 113305e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // If the item was dropped onto this open folder, we have done the work associated 113405e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // with adding the item to the folder, as indicated by mSuppressOnAdd being set 1135bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mSuppressOnAdd) return; 1136bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (!findAndSetEmptyCells(item)) { 1137bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // The current layout is full, can we expand it? 1138bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen setupContentForNumItems(getItemCount() + 1); 1139bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen findAndSetEmptyCells(item); 1140bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1141bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen createAndAddShortcut(item); 1142bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen LauncherModel.addOrMoveItemInDatabase( 1143bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mLauncher, item, mInfo.id, 0, item.cellX, item.cellY); 1144bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1145bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 1146a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public void onRemove(ShortcutInfo item) { 11477c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = true; 114805e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // If this item is being dragged from this open folder, we have already handled 114905e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // the work associated with removing the item, so we don't have to do anything here. 1150bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (item == mCurrentDragInfo) return; 1151df1e4e868a1970b756486dadd652651d40276d36Adam Cohen View v = getViewForInfo(item); 1152a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen mContent.removeView(v); 11532801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (mState == STATE_ANIMATING) { 11542801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mRearrangeOnClose = true; 11552801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } else { 11562801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setupContentForNumItems(getItemCount()); 11572801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1158afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (getItemCount() <= 1) { 1159afb01ee74243cede19088e694ca82cea5983c603Adam Cohen replaceFolderWithFinalItem(); 1160afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 1161a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 11627c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen 1163df1e4e868a1970b756486dadd652651d40276d36Adam Cohen private View getViewForInfo(ShortcutInfo item) { 1164df1e4e868a1970b756486dadd652651d40276d36Adam Cohen for (int j = 0; j < mContent.getCountY(); j++) { 1165df1e4e868a1970b756486dadd652651d40276d36Adam Cohen for (int i = 0; i < mContent.getCountX(); i++) { 1166df1e4e868a1970b756486dadd652651d40276d36Adam Cohen View v = mContent.getChildAt(i, j); 1167df1e4e868a1970b756486dadd652651d40276d36Adam Cohen if (v.getTag() == item) { 1168df1e4e868a1970b756486dadd652651d40276d36Adam Cohen return v; 1169df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1170df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1171df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1172df1e4e868a1970b756486dadd652651d40276d36Adam Cohen return null; 1173df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1174df1e4e868a1970b756486dadd652651d40276d36Adam Cohen 117576078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen public void onItemsChanged() { 1176ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen updateTextViewFocus(); 117776078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 1178ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 117976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void onTitleChanged(CharSequence title) { 118076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 118176078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen 11827c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen public ArrayList<View> getItemsInReadingOrder() { 11837c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (mItemsInvalidated) { 11847c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInReadingOrder.clear(); 11857c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen for (int j = 0; j < mContent.getCountY(); j++) { 11867c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen for (int i = 0; i < mContent.getCountX(); i++) { 11877c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen View v = mContent.getChildAt(i, j); 11887c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (v != null) { 11897a8b82b5926e6a520df28e7f591b9a94ec605581Adam Cohen mItemsInReadingOrder.add(v); 11907c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11917c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11927c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11937c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = false; 11947c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11957c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen return mItemsInReadingOrder; 11967c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11978dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen 11988dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void getLocationInDragLayer(int[] loc) { 11998dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mLauncher.getDragLayer().getLocationInDragLayer(this, loc); 12008dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 1201ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen 1202ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen public void onFocusChange(View v, boolean hasFocus) { 1203ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen if (v == mFolderName && hasFocus) { 1204ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen startEditingFolderName(); 1205ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen } 1206ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen } 12077d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen 12087d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen @Override 12097d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen public void getHitRectRelativeToDragLayer(Rect outRect) { 12107d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen getHitRect(outRect); 12117d30a37007bac318db1c9af47a9af12d348042a5Adam Cohen } 121231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 1213