Folder.java revision 2374abfda3e53f84e005df8923170308e4df8c03
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/* 231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License. 631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at 731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and 1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License. 1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2; 1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 19df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.Animator; 20df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.AnimatorListenerAdapter; 21df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.ObjectAnimator; 22df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.animation.PropertyValuesHolder; 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; 4276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.inputmethod.EditorInfo; 4376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohenimport android.view.inputmethod.InputMethodManager; 4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.LinearLayout; 45df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohenimport android.widget.TextView; 4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 47edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guyimport com.android.launcher.R; 48a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohenimport com.android.launcher2.FolderInfo.FolderListener; 49edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy 50c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohenimport java.util.ArrayList; 513bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohenimport java.util.Collections; 523bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohenimport java.util.Comparator; 53c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen 5431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/** 5531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Represents a set of icons chosen by the user or generated by the system. 5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 578dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohenpublic class Folder extends LinearLayout implements DragSource, View.OnClickListener, 58ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener, 59ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen View.OnFocusChangeListener { 604eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen private static final String TAG = "Launcher.Folder"; 61df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 624eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen protected DragController mDragController; 6331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected Launcher mLauncher; 6431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected FolderInfo mInfo; 6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 66df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static final int STATE_NONE = -1; 67df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static final int STATE_SMALL = 0; 68df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static final int STATE_ANIMATING = 1; 69df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static final int STATE_OPEN = 2; 70df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 71df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private int mExpandDuration; 72df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen protected CellLayout mContent; 73df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private final LayoutInflater mInflater; 74df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private final IconCache mIconCache; 75df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private int mState = STATE_NONE; 76bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private static final int REORDER_ANIMATION_DURATION = 230; 77bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private static final int ON_EXIT_CLOSE_DELAY = 800; 782801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private boolean mRearrangeOnClose = false; 792801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private FolderIcon mFolderIcon; 802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private int mMaxCountX; 812801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private int mMaxCountY; 8278dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen private int mMaxNumItems; 837c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); 84badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen private Drawable mIconDrawable; 857c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen boolean mItemsInvalidated = false; 86bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private ShortcutInfo mCurrentDragInfo; 87bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private View mCurrentDragView; 88bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen boolean mSuppressOnAdd = false; 89bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private int[] mTargetCell = new int[2]; 90bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private int[] mPreviousTargetCell = new int[2]; 91bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private int[] mEmptyCell = new int[2]; 92bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private Alarm mReorderAlarm = new Alarm(); 93bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private Alarm mOnExitAlarm = new Alarm(); 9476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private int mFolderNameHeight; 958e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen private Rect mTempRect = new Rect(); 9667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen private boolean mDragInProgress = false; 9767bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen private boolean mDeleteFolderOnDropCompleted = false; 9867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen private boolean mSuppressFolderDeletion = false; 9905e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen private boolean mItemAddedBackToSelfViaIcon = false; 100ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen FolderEditText mFolderName; 101268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen private float mFolderIconPivotX; 102268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen private float mFolderIconPivotY; 103228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 10476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private boolean mIsEditingName = false; 10576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private InputMethodManager mInputMethodManager; 106df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 107a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen private static String sDefaultFolderName; 108a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen private static String sHintText; 1090121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka private ObjectAnimator mOpenCloseAnimator; 110a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen 111fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen private boolean mDestroyed; 112fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Used to inflate the Workspace from XML. 11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param context The application's context. 11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param attrs The attribtues set containing the Workspace's customization values. 11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public Folder(Context context, AttributeSet attrs) { 12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, attrs); 12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project setAlwaysDrawnWithCacheEnabled(false); 122df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mInflater = LayoutInflater.from(context); 123df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache(); 12478dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen 12578dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen Resources res = getResources(); 12678dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen mMaxCountX = res.getInteger(R.integer.folder_max_count_x); 12778dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen mMaxCountY = res.getInteger(R.integer.folder_max_count_y); 12878dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen mMaxNumItems = res.getInteger(R.integer.folder_max_num_items); 12978dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen if (mMaxCountX < 0 || mMaxCountY < 0 || mMaxNumItems < 0) { 13078dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen mMaxCountX = LauncherModel.getCellCountX(); 13178dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen mMaxCountY = LauncherModel.getCellCountY(); 13278dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen mMaxNumItems = mMaxCountX * mMaxCountY; 13378dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen } 13476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 13576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mInputMethodManager = (InputMethodManager) 1368b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 13776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 13876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mExpandDuration = res.getInteger(R.integer.config_folderAnimDuration); 1394ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen 1404ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen if (sDefaultFolderName == null) { 1414ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen sDefaultFolderName = res.getString(R.string.folder_name); 1424ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } 143a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen if (sHintText == null) { 144a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen sHintText = res.getString(R.string.folder_hint_text); 145a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen } 1464eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen mLauncher = (Launcher) context; 147ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // We need this view to be focusable in touch mode so that when text editing of the folder 148ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // name is complete, we have something to focus on, thus hiding the cursor and giving 149ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // reliable behvior when clicking the text field (since it will always gain focus on click). 150ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen setFocusableInTouchMode(true); 15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project protected void onFinishInflate() { 15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super.onFinishInflate(); 156df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mContent = (CellLayout) findViewById(R.id.folder_content); 1572801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.setGridSize(0, 0); 158a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false); 1592374abfda3e53f84e005df8923170308e4df8c03Adam Cohen mContent.setInvertIfRtl(true); 160ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName = (FolderEditText) findViewById(R.id.folder_name); 161ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setFolder(this); 162ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen mFolderName.setOnFocusChangeListener(this); 16376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 16476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // We find out how tall the text view wants to be (it is set to wrap_content), so that 16576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // we can allocate the appropriate amount of space for it. 16676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen int measureSpec = MeasureSpec.UNSPECIFIED; 16776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.measure(measureSpec, measureSpec); 16876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderNameHeight = mFolderName.getMeasuredHeight(); 16976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 17076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen // We disable action mode for now since it messes up the view on phones 17176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback); 17276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mFolderName.setOnEditorActionListener(this); 1734ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setSelectAllOnFocus(true); 1747a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohen mFolderName.setInputType(mFolderName.getInputType() | 1757a14d0bddea652ddca855af0c413e47a6c1360b2Adam Cohen InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_CAP_WORDS); 17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 1772801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 17876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { 17976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 18076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 18176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 18276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 18376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onCreateActionMode(ActionMode mode, Menu menu) { 18476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 18576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 18676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 18776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void onDestroyActionMode(ActionMode mode) { 18876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 18976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 19076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 19176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 19276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 19376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen }; 19476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void onClick(View v) { 196df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen Object tag = v.getTag(); 197df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (tag instanceof ShortcutInfo) { 198df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen // refactor this code from Folder 199df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ShortcutInfo item = (ShortcutInfo) tag; 200df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen int[] pos = new int[2]; 201df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen v.getLocationOnScreen(pos); 202df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen item.intent.setSourceBounds(new Rect(pos[0], pos[1], 203df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen pos[0] + v.getWidth(), pos[1] + v.getHeight())); 204c7450e3ebd7672fcd7b9d51a8c1e68f63c5ce86bWinson Chung 205c7450e3ebd7672fcd7b9d51a8c1e68f63c5ce86bWinson Chung mLauncher.startActivitySafely(v, item.intent, item); 206df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 20931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean onLongClick(View v) { 21036a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung // Return if global dragging is not enabled 21136a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung if (!mLauncher.isDraggingEnabled()) return true; 21236a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung 213df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen Object tag = v.getTag(); 214df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (tag instanceof ShortcutInfo) { 215df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ShortcutInfo item = (ShortcutInfo) tag; 216df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (!v.isInTouchMode()) { 217df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return false; 218df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 219df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 2207d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung mLauncher.dismissFolderCling(null); 2217d7541e7b48fdc114c24b3b0aa75e70d7228041eWinson Chung 222df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mLauncher.getWorkspace().onDragStartedWithItem(v); 223ac8c87687b8e063c981f28cb31bab2cc110f26ccAdam Cohen mLauncher.getWorkspace().beginDragShared(v, this); 224badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen mIconDrawable = ((TextView) v).getCompoundDrawables()[1]; 22576078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen 22676078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen mCurrentDragInfo = item; 227bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mEmptyCell[0] = item.cellX; 228bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mEmptyCell[1] = item.cellY; 229bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragView = v; 230fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen 231fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mContent.removeView(mCurrentDragView); 232fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mInfo.remove(mCurrentDragInfo); 23367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDragInProgress = true; 23405e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = false; 235df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return true; 23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 23976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean isEditingName() { 24076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return mIsEditingName; 24176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 24276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 24376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void startEditingFolderName() { 244a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen mFolderName.setHint(""); 24576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mIsEditingName = true; 24676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 24776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 24876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void dismissEditingName() { 24976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); 25076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen doneEditingFolderName(true); 25176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 25276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 25376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void doneEditingFolderName(boolean commit) { 254a65beeea13c18c443f15f8d51c4c6e153a6c4ef9Adam Cohen mFolderName.setHint(sHintText); 2551df26a368a135395b7bd61e9b109044b33b1b0beAdam Cohen // Convert to a string here to ensure that no other state associated with the text field 2561df26a368a135395b7bd61e9b109044b33b1b0beAdam Cohen // gets saved. 2573371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen String newTitle = mFolderName.getText().toString(); 2583371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mInfo.setTitle(newTitle); 25976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen LauncherModel.updateItemInDatabase(mLauncher, mInfo); 260ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 2613371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen if (commit) { 2623371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 2638b805b17158886035b38261eb611d8641701ae43Michael Jurka String.format(getContext().getString(R.string.folder_renamed), newTitle)); 2643371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 265ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // In order to clear the focus from the text field, we set the focus on ourself. This 266ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // ensures that every time the field is clicked, focus is gained, giving reliable behavior. 267ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen requestFocus(); 268ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 269e601a43345224e3e386abc68bbea8b08b2df9570Adam Cohen Selection.setSelection((Spannable) mFolderName.getText(), 0, 0); 27076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen mIsEditingName = false; 27176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 27276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 27376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { 27476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen if (actionId == EditorInfo.IME_ACTION_DONE) { 27576fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen dismissEditingName(); 27676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return true; 27776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 27876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return false; 27976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 28076fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 28176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public View getEditTextRegion() { 28276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen return mFolderName; 28376fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 28476fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen 285badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen public Drawable getDragDrawable() { 286badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen return mIconDrawable; 287badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen } 288badf71e11fba2d6efa1d1bcca9542001f90a3777Adam Cohen 2890c872ba544ecfd9b106bb66137da8680927590deAdam Cohen /** 2900c872ba544ecfd9b106bb66137da8680927590deAdam Cohen * We need to handle touch events to prevent them from falling through to the workspace below. 2910c872ba544ecfd9b106bb66137da8680927590deAdam Cohen */ 2920c872ba544ecfd9b106bb66137da8680927590deAdam Cohen @Override 2930c872ba544ecfd9b106bb66137da8680927590deAdam Cohen public boolean onTouchEvent(MotionEvent ev) { 2940c872ba544ecfd9b106bb66137da8680927590deAdam Cohen return true; 2950c872ba544ecfd9b106bb66137da8680927590deAdam Cohen } 2960c872ba544ecfd9b106bb66137da8680927590deAdam Cohen 29700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato public void setDragController(DragController dragController) { 29800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato mDragController = dragController; 29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3012801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen void setFolderIcon(FolderIcon icon) { 3022801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mFolderIcon = icon; 3032801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 3042801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 3053371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen @Override 3063371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 3073371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen // When the folder gets focus, we don't want to announce the list of items. 3083371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen return true; 3093371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 3103371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 31131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @return the FolderInfo object associated with this folder 31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project FolderInfo getInfo() { 31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return mInfo; 31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 31731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3183bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen private class GridComparator implements Comparator<ShortcutInfo> { 3193bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int mNumCols; 3203bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen public GridComparator(int numCols) { 3213bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen mNumCols = numCols; 3223bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3233bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 3243bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen @Override 3253bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen public int compare(ShortcutInfo lhs, ShortcutInfo rhs) { 3263bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int lhIndex = lhs.cellY * mNumCols + lhs.cellX; 3273bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int rhIndex = rhs.cellY * mNumCols + rhs.cellX; 3283bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen return (lhIndex - rhIndex); 3293bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3303bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3313bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 3323bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen private void placeInReadingOrder(ArrayList<ShortcutInfo> items) { 3333bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int maxX = 0; 3343bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int count = items.size(); 3353bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen for (int i = 0; i < count; i++) { 3363bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen ShortcutInfo item = items.get(i); 3373bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen if (item.cellX > maxX) { 3383bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen maxX = item.cellX; 3393bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3403bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 341691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen 342691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen GridComparator gridComparator = new GridComparator(maxX + 1); 3433bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen Collections.sort(items, gridComparator); 3443bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen final int countX = mContent.getCountX(); 3453bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen for (int i = 0; i < count; i++) { 3463bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int x = i % countX; 3473bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen int y = i / countX; 3483bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen ShortcutInfo item = items.get(i); 3493bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen item.cellX = x; 3503bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen item.cellY = y; 3513bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3523bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen } 3533bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project void bind(FolderInfo info) { 35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mInfo = info; 356df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ArrayList<ShortcutInfo> children = info.contents; 357c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen ArrayList<ShortcutInfo> overflow = new ArrayList<ShortcutInfo>(); 3587c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen setupContentForNumItems(children.size()); 3593bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen placeInReadingOrder(children); 3600057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen int count = 0; 361df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen for (int i = 0; i < children.size(); i++) { 362df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen ShortcutInfo child = (ShortcutInfo) children.get(i); 363c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen if (!createAndAddShortcut(child)) { 364c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen overflow.add(child); 3650057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen } else { 3660057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen count++; 367c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 368df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 369c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 3700057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen // We rearrange the items in case there are any empty gaps 3710057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen setupContentForNumItems(count); 3720057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen 373c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // If our folder has too many items we prune them from the list. This is an issue 374c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // when upgrading from the old Folders implementation which could contain an unlimited 375c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // number of items. 376c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen for (ShortcutInfo item: overflow) { 377c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen mInfo.remove(item); 378c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen LauncherModel.deleteItemFromDatabase(mLauncher, item); 379c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 380c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 3814dbe6d993485a702505ee4895db94aaa89655f2cAdam Cohen mItemsInvalidated = true; 382ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen updateTextViewFocus(); 383a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen mInfo.addListener(this); 3844ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen 385afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (!sDefaultFolderName.contentEquals(mInfo.title)) { 3864ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setText(mInfo.title); 3874ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } else { 3884ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen mFolderName.setText(""); 3894ef610fc88e447ff6d6cdd382a7d064be9f739d6Adam Cohen } 390691a5797f9bba4154d564d3a6c9b92559ee8cc4aAdam Cohen updateItemLocationsInDatabase(); 391df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 392df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 393df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen /** 394df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * Creates a new UserFolder, inflated from R.layout.user_folder. 395df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * 396df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * @param context The application's context. 397df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * 398df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * @return A new UserFolder. 399df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen */ 400df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen static Folder fromXml(Context context) { 401df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null); 402df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 403df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 404df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen /** 405df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * This method is intended to make the UserFolder to be visually identical in size and position 406df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen * to its associated FolderIcon. This allows for a seamless transition into the expanded state. 407df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen */ 408df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen private void positionAndSizeAsIcon() { 4093e8f811f31a2275e778244427271f77f4116c08bAdam Cohen if (!(getParent() instanceof DragLayer)) return; 410662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setScaleX(0.8f); 411662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setScaleY(0.8f); 412662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen setAlpha(0f); 413df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_SMALL; 414df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 415df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 416df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void animateOpen() { 4173e8f811f31a2275e778244427271f77f4116c08bAdam Cohen positionAndSizeAsIcon(); 4183e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 4198e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen if (!(getParent() instanceof DragLayer)) return; 4202801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen centerAboutIcon(); 421662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1); 422662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f); 423662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f); 4240121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka final ObjectAnimator oa = mOpenCloseAnimator = 4252ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); 4266441de0ec2a71862798dd51180d0811b42edd514Adam Cohen 4272801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.addListener(new AnimatorListenerAdapter() { 428df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 429df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationStart(Animator animation) { 4303371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 4318b805b17158886035b38261eb611d8641701ae43Michael Jurka String.format(getContext().getString(R.string.folder_opened), 4323371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen mContent.getCountX(), mContent.getCountY())); 433df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_ANIMATING; 434df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 435df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 436df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationEnd(Animator animation) { 4372801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mState = STATE_OPEN; 4380121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_NONE, null); 4397a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung Cling cling = mLauncher.showFirstRunFoldersCling(); 4407a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung if (cling != null) { 4417a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung cling.bringToFront(); 4427a74ac9cd68db5e8bba87bbda43f73cea9c427c8Winson Chung } 443ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen setFocusOnFirstChild(); 444df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 445df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen }); 4462801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.setDuration(mExpandDuration); 4470121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_HARDWARE, null); 448f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka oa.start(); 449df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 450df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 4513371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen private void sendCustomAccessibilityEvent(int type, String text) { 4528b805b17158886035b38261eb611d8641701ae43Michael Jurka AccessibilityManager accessibilityManager = (AccessibilityManager) 4538b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); 4548b805b17158886035b38261eb611d8641701ae43Michael Jurka if (accessibilityManager.isEnabled()) { 4553371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen AccessibilityEvent event = AccessibilityEvent.obtain(type); 4563371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen onInitializeAccessibilityEvent(event); 4573371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen event.getText().add(text); 4588b805b17158886035b38261eb611d8641701ae43Michael Jurka accessibilityManager.sendAccessibilityEvent(event); 4593371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 4603371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen } 4613371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen 462ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private void setFocusOnFirstChild() { 463ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View firstChild = mContent.getChildAt(0, 0); 464ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (firstChild != null) { 465ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen firstChild.requestFocus(); 466ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 467ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 468ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 469df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void animateClosed() { 4708e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen if (!(getParent() instanceof DragLayer)) return; 471662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0); 472662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f); 473662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f); 4740121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka final ObjectAnimator oa = mOpenCloseAnimator = 4752ecf995e0d2d55eb71d03f7230ca87270872d1a3Michael Jurka LauncherAnimUtils.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); 476df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 4772801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.addListener(new AnimatorListenerAdapter() { 478df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 479df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationEnd(Animator animation) { 4802801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen onCloseComplete(); 4810121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_NONE, null); 4822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mState = STATE_SMALL; 483df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 484df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen @Override 485df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public void onAnimationStart(Animator animation) { 4863371da0159cc54ff8ae1b1b26effb96445f208d5Adam Cohen sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, 4878b805b17158886035b38261eb611d8641701ae43Michael Jurka getContext().getString(R.string.folder_closed)); 488df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mState = STATE_ANIMATING; 489df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 490df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen }); 4912801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen oa.setDuration(mExpandDuration); 4920121c3ea3d5bae176af193ea8ef23ae8a868dd31Michael Jurka setLayerType(LAYER_TYPE_HARDWARE, null); 493f1ad608c28c79c8e9b83d83ce9154f1b7284f412Michael Jurka oa.start(); 494df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 495df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 496df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen void notifyDataSetChanged() { 497df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen // recreate all the children if the data set changes under us. We may want to do this more 498df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen // intelligently (ie just removing the views that should no longer exist) 499df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mContent.removeAllViewsInLayout(); 500df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen bind(mInfo); 501df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 502df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 503cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen public boolean acceptDrop(DragObject d) { 504cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen final ItemInfo item = (ItemInfo) d.dragInfo; 505df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen final int itemType = item.itemType; 5062801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || 5072801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) && 5082801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen !isFull()); 509df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 510df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 511df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen protected boolean findAndSetEmptyCells(ShortcutInfo item) { 512df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen int[] emptyCell = new int[2]; 513df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) { 514df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen item.cellX = emptyCell[0]; 515df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen item.cellY = emptyCell[1]; 516df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return true; 517df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } else { 518df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return false; 519df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 520df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 521df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 522c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen protected boolean createAndAddShortcut(ShortcutInfo item) { 523df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen final TextView textView = 524e87b924efaaf1cfb555a4327dc653929a4c182f1Adam Cohen (TextView) mInflater.inflate(R.layout.application, this, false); 525df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setCompoundDrawablesWithIntrinsicBounds(null, 526df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen new FastBitmapDrawable(item.getIcon(mIconCache)), null, null); 527df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setText(item.title); 528df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setTag(item); 529df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 530df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setOnClickListener(this); 531df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen textView.setOnLongClickListener(this); 532df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 533c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen // We need to check here to verify that the given item's location isn't already occupied 5343bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen // by another item. 5350057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen if (mContent.getChildAt(item.cellX, item.cellY) != null || item.cellX < 0 || item.cellY < 0 5360057bbcfa4a2ee12c5e87cba8c3fac8eadb078edAdam Cohen || item.cellX >= mContent.getCountX() || item.cellY >= mContent.getCountY()) { 5373bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen // This shouldn't happen, log it. 5383bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen Log.e(TAG, "Folder order not properly persisted during bind"); 539c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen if (!findAndSetEmptyCells(item)) { 540c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen return false; 541c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 542c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen } 543c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen 544df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen CellLayout.LayoutParams lp = 545df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY); 546df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen boolean insert = false; 547ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen textView.setOnKeyListener(new FolderKeyEventListener()); 548df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true); 549c508b2d701ef980875f7ebc71bf2d87781159478Adam Cohen return true; 550df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 551df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 552cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen public void onDragEnter(DragObject d) { 553bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mPreviousTargetCell[0] = -1; 554bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mPreviousTargetCell[1] = -1; 555bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.cancelAlarm(); 556df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 557df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 558bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen OnAlarmListener mReorderAlarmListener = new OnAlarmListener() { 559bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAlarm(Alarm alarm) { 560bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen realTimeReorder(mEmptyCell, mTargetCell); 561bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 562bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen }; 563bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 564bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen boolean readingOrderGreaterThan(int[] v1, int[] v2) { 565bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) { 566bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return true; 567bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 568bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return false; 569bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 570df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 571df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 572bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private void realTimeReorder(int[] empty, int[] target) { 573bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen boolean wrap; 574bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int startX; 575bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int endX; 576bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int startY; 57776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen int delay = 0; 57876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen float delayAmount = 30; 579bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (readingOrderGreaterThan(target, empty)) { 580bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen wrap = empty[0] >= mContent.getCountX() - 1; 581bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startY = wrap ? empty[1] + 1 : empty[1]; 582bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int y = startY; y <= target[1]; y++) { 583bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startX = y == empty[1] ? empty[0] + 1 : 0; 584bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen endX = y < target[1] ? mContent.getCountX() - 1 : target[0]; 585bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int x = startX; x <= endX; x++) { 586bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen View v = mContent.getChildAt(x,y); 587bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mContent.animateChildToPosition(v, empty[0], empty[1], 588482ed823afb4c7452e037ce8add7ea425fc83da2Adam Cohen REORDER_ANIMATION_DURATION, delay, true, true)) { 589bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[0] = x; 590bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[1] = y; 59176fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delay += delayAmount; 59276fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delayAmount *= 0.9; 593bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 594bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 595bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 596bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 597bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen wrap = empty[0] == 0; 598bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startY = wrap ? empty[1] - 1 : empty[1]; 599bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int y = startY; y >= target[1]; y--) { 600bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1; 601bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen endX = y > target[1] ? 0 : target[0]; 602bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen for (int x = startX; x >= endX; x--) { 603bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen View v = mContent.getChildAt(x,y); 604bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mContent.animateChildToPosition(v, empty[0], empty[1], 605482ed823afb4c7452e037ce8add7ea425fc83da2Adam Cohen REORDER_ANIMATION_DURATION, delay, true, true)) { 606bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[0] = x; 607bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen empty[1] = y; 60876fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delay += delayAmount; 60976fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen delayAmount *= 0.9; 610bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 611bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 612bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 613bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 614bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 615bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 6162374abfda3e53f84e005df8923170308e4df8c03Adam Cohen public boolean isLayoutRtl() { 6172374abfda3e53f84e005df8923170308e4df8c03Adam Cohen return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 6182374abfda3e53f84e005df8923170308e4df8c03Adam Cohen } 6192374abfda3e53f84e005df8923170308e4df8c03Adam Cohen 620bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDragOver(DragObject d) { 621bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, null); 622bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1], 1, 1, mTargetCell); 623bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 6242374abfda3e53f84e005df8923170308e4df8c03Adam Cohen if (isLayoutRtl()) { 6252374abfda3e53f84e005df8923170308e4df8c03Adam Cohen mTargetCell[0] = mContent.getCountX() - mTargetCell[0] - 1; 6262374abfda3e53f84e005df8923170308e4df8c03Adam Cohen } 6272374abfda3e53f84e005df8923170308e4df8c03Adam Cohen 628bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mTargetCell[0] != mPreviousTargetCell[0] || mTargetCell[1] != mPreviousTargetCell[1]) { 629bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mReorderAlarm.cancelAlarm(); 630bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mReorderAlarm.setOnAlarmListener(mReorderAlarmListener); 631bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mReorderAlarm.setAlarm(150); 632bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mPreviousTargetCell[0] = mTargetCell[0]; 633bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mPreviousTargetCell[1] = mTargetCell[1]; 634bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 635df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 636df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 637bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // This is used to compute the visual center of the dragView. The idea is that 638bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // the visual center represents the user's interpretation of where the item is, and hence 639bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // is the appropriate point to use when determining drop location. 640bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset, 641bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen DragView dragView, float[] recycle) { 642bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen float res[]; 643bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (recycle == null) { 644bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res = new float[2]; 645bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 646bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res = recycle; 647df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 6482801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 649bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // These represent the visual top and left of drag view if a dragRect was provided. 650bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // If a dragRect was not provided, then they correspond to the actual view left and 651bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // top, as the dragRect is in that case taken to be the entire dragView. 652bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // R.dimen.dragViewOffsetY. 653bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int left = x - xOffset; 654bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen int top = y - yOffset; 655bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 656bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // In order to find the visual center, we shift by half the dragRect 657bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res[0] = left + dragView.getDragRegion().width() / 2; 658bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen res[1] = top + dragView.getDragRegion().height() / 2; 659bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 660bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen return res; 661bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 662bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 663bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() { 664bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAlarm(Alarm alarm) { 6653e8f811f31a2275e778244427271f77f4116c08bAdam Cohen completeDragExit(); 666bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 667bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen }; 6682801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 66995bb800de9b0142bea0110b074eddbcf0e475736Adam Cohen public void completeDragExit() { 6703e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mLauncher.closeFolder(); 6713e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mCurrentDragInfo = null; 6723e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mCurrentDragView = null; 6733e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mSuppressOnAdd = false; 6743e8f811f31a2275e778244427271f77f4116c08bAdam Cohen mRearrangeOnClose = true; 6753e8f811f31a2275e778244427271f77f4116c08bAdam Cohen } 6763e8f811f31a2275e778244427271f77f4116c08bAdam Cohen 677bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDragExit(DragObject d) { 678bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // We only close the folder if this is a true drag exit, ie. not because a drop 679bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // has occurred above the folder. 680bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (!d.dragComplete) { 681bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener); 682bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY); 683bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 684bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mReorderAlarm.cancelAlarm(); 6852801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 6862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 687a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete, 688a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung boolean success) { 68967bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (success) { 69005e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen if (mDeleteFolderOnDropCompleted && !mItemAddedBackToSelfViaIcon) { 69167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen replaceFolderWithFinalItem(); 69267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 69367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } else { 69467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen // The drag failed, we need to return the item to the folder 69567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mFolderIcon.onDrop(d); 69667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen 69767bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen // We're going to trigger a "closeFolder" which may occur before this item has 69867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen // been added back to the folder -- this could cause the folder to be deleted 69967bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (mOnExitAlarm.alarmPending()) { 70067bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mSuppressFolderDeletion = true; 70167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 70267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 70367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen 70467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (target != this) { 70567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (mOnExitAlarm.alarmPending()) { 70667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mOnExitAlarm.cancelAlarm(); 70767bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen completeDragExit(); 70867bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 70967bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 71067bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDeleteFolderOnDropCompleted = false; 71167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDragInProgress = false; 71205e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = false; 713bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragInfo = null; 714bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mCurrentDragView = null; 715bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mSuppressOnAdd = false; 7164045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen 7174045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen // Reordering may have occured, and we need to save the new item locations. We do this once 7184045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen // at the end to prevent unnecessary database operations. 7194045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen updateItemLocationsInDatabase(); 7204045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen } 7214045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen 722a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung @Override 723043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public boolean supportsFlingToDelete() { 724043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return true; 725043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 726043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 727a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung public void onFlingToDelete(DragObject d, int x, int y, PointF vec) { 728a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // Do nothing 729a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 730a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 731a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung @Override 732a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung public void onFlingToDeleteCompleted() { 733a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // Do nothing 734a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 735a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 7364045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen private void updateItemLocationsInDatabase() { 7374045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen ArrayList<View> list = getItemsInReadingOrder(); 7384045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen for (int i = 0; i < list.size(); i++) { 7394045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen View v = list.get(i); 7404045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen ItemInfo info = (ItemInfo) v.getTag(); 7414045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen LauncherModel.moveItemInDatabase(mLauncher, info, mInfo.id, 0, 7424045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen info.cellX, info.cellY); 7434045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen } 74467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 745228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 74667bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen public void notifyDrop() { 74767bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (mDragInProgress) { 74805e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen mItemAddedBackToSelfViaIcon = true; 74976078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 750df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 751df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 752df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen public boolean isDropEnabled() { 753df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return true; 754df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen } 755df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen 756cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen public DropTarget getDropTargetDelegate(DragObject d) { 757df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen return null; 75831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 759a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 7604045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen private void setupContentDimensions(int count) { 7612801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen ArrayList<View> list = getItemsInReadingOrder(); 7622801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 7632801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int countX = mContent.getCountX(); 7642801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int countY = mContent.getCountY(); 7657c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen boolean done = false; 7667c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen 7677c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen while (!done) { 7687c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen int oldCountX = countX; 7697c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen int oldCountY = countY; 7707c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (countX * countY < count) { 7717c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen // Current grid is too small, expand it 77278dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen if ((countX <= countY || countY == mMaxCountY) && countX < mMaxCountX) { 7737c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countX++; 7747c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if (countY < mMaxCountY) { 7757c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countY++; 7767c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 7777c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (countY == 0) countY++; 7787c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if ((countY - 1) * countX >= count && countY >= countX) { 7797c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countY = Math.max(0, countY - 1); 7807c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } else if ((countX - 1) * countY >= count) { 7817c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen countX = Math.max(0, countX - 1); 7822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 7837c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen done = countX == oldCountX && countY == oldCountY; 7842801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 7857c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mContent.setGridSize(countX, countY); 7862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen arrangeChildren(list); 7872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 7882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 7892801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen public boolean isFull() { 79078dc83e875fdf541881cfb867ec38bee21d546e9Adam Cohen return getItemCount() >= mMaxNumItems; 7912801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 7922801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 7932801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void centerAboutIcon() { 7948e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); 7952801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 7962801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); 797f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight() 798f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen + mFolderNameHeight; 7998e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer parent = (DragLayer) mLauncher.findViewById(R.id.drag_layer); 8008e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen 801307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect); 8022801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 803307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen int centerX = (int) (mTempRect.left + mTempRect.width() * scale / 2); 804307fe23f125cbbd5512ad8d4660025f2ab68f30bAdam Cohen int centerY = (int) (mTempRect.top + mTempRect.height() * scale / 2); 8052801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int centeredLeft = centerX - width / 2; 8062801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int centeredTop = centerY - height / 2; 8072801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8087cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen int currentPage = mLauncher.getWorkspace().getCurrentPage(); 8097cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // In case the workspace is scrolling, we need to use the final scroll to compute 8107cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // the folders bounds. 8117cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen mLauncher.getWorkspace().setFinalScrollForPageChange(currentPage); 81235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // We first fetch the currently visible CellLayoutChildren 8137cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen CellLayout currentLayout = (CellLayout) mLauncher.getWorkspace().getChildAt(currentPage); 814a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka ShortcutAndWidgetContainer boundingLayout = currentLayout.getShortcutsAndWidgets(); 81535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen Rect bounds = new Rect(); 81635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen parent.getDescendantRectRelativeToSelf(boundingLayout, bounds); 8177cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen // We reset the workspaces scroll 8187cc1bc4b657630250515ee8b1f65b77417e4c9b3Adam Cohen mLauncher.getWorkspace().resetFinalScrollForPageChange(currentPage); 81935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen 82035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // We need to bound the folder to the currently visible CellLayoutChildren 82135e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen int left = Math.min(Math.max(bounds.left, centeredLeft), 82235e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen bounds.left + bounds.width() - width); 82335e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen int top = Math.min(Math.max(bounds.top, centeredTop), 82435e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen bounds.top + bounds.height() - height); 82535e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen // If the folder doesn't fit within the bounds, center it about the desired bounds 82635e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen if (width >= bounds.width()) { 82735e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen left = bounds.left + (bounds.width() - width) / 2; 82835e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen } 82935e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen if (height >= bounds.height()) { 83035e7e64d4b98e42c760e5e91489b7014a6ba9073Adam Cohen top = bounds.top + (bounds.height() - height) / 2; 8310e4857c302da6adbd45231d7a8bae0289fa33250Adam Cohen } 8322801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8332801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int folderPivotX = width / 2 + (centeredLeft - left); 8342801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int folderPivotY = height / 2 + (centeredTop - top); 8352801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setPivotX(folderPivotX); 8362801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setPivotY(folderPivotY); 837268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen mFolderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() * 8382801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen (1.0f * folderPivotX / width)); 839268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen mFolderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() * 8402801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen (1.0f * folderPivotY / height)); 8413bf84d3250bf45f2a5b041245e9bd327e03e22c0Adam Cohen 842662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.width = width; 843662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.height = height; 844662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.x = left; 845662b598c86a1772d95303ef9c921d4bbe342387bAdam Cohen lp.y = top; 8462801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8472801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 848268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen float getPivotXForIconAnimation() { 849268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen return mFolderIconPivotX; 850268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen } 851268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen float getPivotYForIconAnimation() { 852268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen return mFolderIconPivotY; 853268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen } 854268c4751b547e1470a94030af73a4e7bb8ea221eAdam Cohen 8552801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void setupContentForNumItems(int count) { 8564045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen setupContentDimensions(count); 8572801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8588e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); 8592801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (lp == null) { 8608e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen lp = new DragLayer.LayoutParams(0, 0); 8618e776a62c5cc60737f5cdbbeacfec5f958112fa7Adam Cohen lp.customPosition = true; 8622801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setLayoutParams(lp); 8632801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8642801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen centerAboutIcon(); 8652801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8662801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 867234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 868234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); 869f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight() 870f4bb1cdecd3cf866a1d87b7b8560234fa7dd4cc5Adam Cohen + mFolderNameHeight; 871234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen 872234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen int contentWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(), 873234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.EXACTLY); 874234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen int contentHeightSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredHeight(), 875234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.EXACTLY); 876234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen mContent.measure(contentWidthSpec, contentHeightSpec); 877234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen 878234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen mFolderName.measure(contentWidthSpec, 879234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY)); 880234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen setMeasuredDimension(width, height); 881234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen } 882234c4cd54406e363a2ebc213f6ae5be284414988Adam Cohen 8832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void arrangeChildren(ArrayList<View> list) { 8842801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen int[] vacant = new int[2]; 8852801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (list == null) { 8862801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen list = getItemsInReadingOrder(); 8872801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 8882801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.removeAllViews(); 8892801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 8902801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen for (int i = 0; i < list.size(); i++) { 8912801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen View v = list.get(i); 8922801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.getVacantCell(vacant, 1, 1); 8932801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams(); 8942801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen lp.cellX = vacant[0]; 8952801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen lp.cellY = vacant[1]; 8962801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen ItemInfo info = (ItemInfo) v.getTag(); 8972792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen if (info.cellX != vacant[0] || info.cellY != vacant[1]) { 8982792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellX = vacant[0]; 8992792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellY = vacant[1]; 9002792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0, 9012792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen info.cellX, info.cellY); 9022792a33ecc9b2def0cdd31756c45f5fe73cf13acAdam Cohen } 9032801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen boolean insert = false; 9042801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true); 9052801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9067c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = true; 9072801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9082801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 909a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public int getItemCount() { 910a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka return mContent.getShortcutsAndWidgets().getChildCount(); 911a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 912a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 913a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public View getItemAt(int index) { 914a52570f8f9ad65b85e33a2f2e87722f9edd6c6f4Michael Jurka return mContent.getShortcutsAndWidgets().getChildAt(index); 915a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 916a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen 9172801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen private void onCloseComplete() { 91805e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen DragLayer parent = (DragLayer) getParent(); 9195649c287039ea7908112b41604c3fc2893c4697eMichael Jurka if (parent != null) { 9205649c287039ea7908112b41604c3fc2893c4697eMichael Jurka parent.removeView(this); 9215649c287039ea7908112b41604c3fc2893c4697eMichael Jurka } 9224554ee16f122a3dbd9a8d3b828f1c8c7e7b7fe99Adam Cohen mDragController.removeDropTarget((DropTarget) this); 92305e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen clearFocus(); 924ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderIcon.requestFocus(); 92505e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen 9262801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (mRearrangeOnClose) { 9272801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setupContentForNumItems(getItemCount()); 9282801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mRearrangeOnClose = false; 9292801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 930afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (getItemCount() <= 1) { 93167bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen if (!mDragInProgress && !mSuppressFolderDeletion) { 93267bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen replaceFolderWithFinalItem(); 93367bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } else if (mDragInProgress) { 93467bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mDeleteFolderOnDropCompleted = true; 93567bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen } 936afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 93767bd9ccf856840856944815a382e4bbb0e71e949Adam Cohen mSuppressFolderDeletion = false; 938afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 939afb01ee74243cede19088e694ca82cea5983c603Adam Cohen 940afb01ee74243cede19088e694ca82cea5983c603Adam Cohen private void replaceFolderWithFinalItem() { 941fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // Add the last remaining child to the workspace in place of the folder 942fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen Runnable onCompleteRunnable = new Runnable() { 943fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen @Override 944fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen public void run() { 945fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screen); 946fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen 947c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen View child = null; 948fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen // Move the item from the folder to the workspace, in the position of the folder 949fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (getItemCount() == 1) { 950fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen ShortcutInfo finalItem = mInfo.contents.get(0); 951c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen child = mLauncher.createShortcut(R.layout.application, cellLayout, 952fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen finalItem); 953fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container, 954fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mInfo.screen, mInfo.cellX, mInfo.cellY); 955fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 956487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen if (getItemCount() <= 1) { 957487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen // Remove the folder 958487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen LauncherModel.deleteItemFromDatabase(mLauncher, mInfo); 959487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen cellLayout.removeView(mFolderIcon); 960487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen if (mFolderIcon instanceof DropTarget) { 961487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen mDragController.removeDropTarget((DropTarget) mFolderIcon); 962487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen } 963487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen mLauncher.removeFolder(mInfo); 964487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen } 965c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen // We add the child after removing the folder to prevent both from existing at 966c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen // the same time in the CellLayout. 967c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen if (child != null) { 968c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screen, 969c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY); 970c5e63f3dc7f19d0da8380e425894450302700ab9Adam Cohen } 971fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 972fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen }; 973fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen View finalChild = getItemAt(0); 974fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen if (finalChild != null) { 975fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mFolderIcon.performDestroyAnimation(finalChild, onCompleteRunnable); 976afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 977fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen mDestroyed = true; 978fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen } 979afb01ee74243cede19088e694ca82cea5983c603Adam Cohen 980fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen boolean isDestroyed() { 981fb91f303f5e672f9b4c4f9f8a03486b224d60cd6Adam Cohen return mDestroyed; 9822801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 9832801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen 984ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // This method keeps track of the last item in the folder for the purposes 985ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen // of keyboard focus 986ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen private void updateTextViewFocus() { 987ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen View lastChild = getItemAt(getItemCount() - 1); 988ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen getItemAt(getItemCount() - 1); 989ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen if (lastChild != null) { 990ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusDownId(lastChild.getId()); 991ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusRightId(lastChild.getId()); 992ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusLeftId(lastChild.getId()); 993ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen mFolderName.setNextFocusUpId(lastChild.getId()); 994ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 995ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen } 996ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 997bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onDrop(DragObject d) { 998bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen ShortcutInfo item; 999bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (d.dragInfo instanceof ApplicationInfo) { 1000bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // Came from all apps -- make a copy 1001bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item = ((ApplicationInfo) d.dragInfo).makeShortcut(); 1002bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item.spanX = 1; 1003bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item.spanY = 1; 1004bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } else { 1005bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen item = (ShortcutInfo) d.dragInfo; 1006bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 100705e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // Dragged from self onto self, currently this is the only path possible, however 100805e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // we keep this as a distinct code path. 1009bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (item == mCurrentDragInfo) { 1010bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag(); 1011bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams(); 1012bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen si.cellX = lp.cellX = mEmptyCell[0]; 1013bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen si.cellX = lp.cellY = mEmptyCell[1]; 1014bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true); 1015fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen if (d.dragView.hasDrawn()) { 1016fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, mCurrentDragView); 1017fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen } else { 10182c4cf411f6c30fb2bfb47d2b13b680bda7a266dcWinson Chung d.deferDragViewCleanupPostAnimation = false; 1019fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen mCurrentDragView.setVisibility(VISIBLE); 1020fc53cd22c9a78708c78c85946443f23ec8c59502Adam Cohen } 1021e9166b247addcf67542ababb9d453f5bfb33c7b2Adam Cohen mItemsInvalidated = true; 10224045eb736e76374ec8b53b4cea2eaea47c72db4aAdam Cohen setupContentDimensions(getItemCount()); 1023716b51e030f9c6ed34af2b947760e46a280c65a6Adam Cohen mSuppressOnAdd = true; 1024bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1025bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mInfo.add(item); 1026bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1027bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 1028bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen public void onAdd(ShortcutInfo item) { 1029bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mItemsInvalidated = true; 103005e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // If the item was dropped onto this open folder, we have done the work associated 103105e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // with adding the item to the folder, as indicated by mSuppressOnAdd being set 1032bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (mSuppressOnAdd) return; 1033bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (!findAndSetEmptyCells(item)) { 1034bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen // The current layout is full, can we expand it? 1035bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen setupContentForNumItems(getItemCount() + 1); 1036bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen findAndSetEmptyCells(item); 1037bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1038bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen createAndAddShortcut(item); 1039bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen LauncherModel.addOrMoveItemInDatabase( 1040bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen mLauncher, item, mInfo.id, 0, item.cellX, item.cellY); 1041bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen } 1042bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen 1043a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen public void onRemove(ShortcutInfo item) { 10447c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = true; 104505e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // If this item is being dragged from this open folder, we have already handled 104605e0f40e50574f50678a9e1461cb245cddc46abbAdam Cohen // the work associated with removing the item, so we don't have to do anything here. 1047bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen if (item == mCurrentDragInfo) return; 1048df1e4e868a1970b756486dadd652651d40276d36Adam Cohen View v = getViewForInfo(item); 1049a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen mContent.removeView(v); 10502801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen if (mState == STATE_ANIMATING) { 10512801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen mRearrangeOnClose = true; 10522801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } else { 10532801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen setupContentForNumItems(getItemCount()); 10542801cafe62653131fdc9da402e5c44e5ffd0bf47Adam Cohen } 1055afb01ee74243cede19088e694ca82cea5983c603Adam Cohen if (getItemCount() <= 1) { 1056afb01ee74243cede19088e694ca82cea5983c603Adam Cohen replaceFolderWithFinalItem(); 1057afb01ee74243cede19088e694ca82cea5983c603Adam Cohen } 1058a9cf38f533d1e86269868f1e6a806ccffd4a78fcAdam Cohen } 10597c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen 1060df1e4e868a1970b756486dadd652651d40276d36Adam Cohen private View getViewForInfo(ShortcutInfo item) { 1061df1e4e868a1970b756486dadd652651d40276d36Adam Cohen for (int j = 0; j < mContent.getCountY(); j++) { 1062df1e4e868a1970b756486dadd652651d40276d36Adam Cohen for (int i = 0; i < mContent.getCountX(); i++) { 1063df1e4e868a1970b756486dadd652651d40276d36Adam Cohen View v = mContent.getChildAt(i, j); 1064df1e4e868a1970b756486dadd652651d40276d36Adam Cohen if (v.getTag() == item) { 1065df1e4e868a1970b756486dadd652651d40276d36Adam Cohen return v; 1066df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1067df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1068df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1069df1e4e868a1970b756486dadd652651d40276d36Adam Cohen return null; 1070df1e4e868a1970b756486dadd652651d40276d36Adam Cohen } 1071df1e4e868a1970b756486dadd652651d40276d36Adam Cohen 107276078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen public void onItemsChanged() { 1073ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen updateTextViewFocus(); 107476078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 1075ac56cff1860b71d3f164aedd268703936e08fdc0Adam Cohen 107676fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen public void onTitleChanged(CharSequence title) { 107776fc085d28178a5d4fb3787ede956281a2cc3179Adam Cohen } 107876078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen 10797c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen public ArrayList<View> getItemsInReadingOrder() { 108076078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen return getItemsInReadingOrder(true); 108176078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 108276078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen 108376078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen public ArrayList<View> getItemsInReadingOrder(boolean includeCurrentDragItem) { 10847c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (mItemsInvalidated) { 10857c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInReadingOrder.clear(); 10867c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen for (int j = 0; j < mContent.getCountY(); j++) { 10877c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen for (int i = 0; i < mContent.getCountX(); i++) { 10887c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen View v = mContent.getChildAt(i, j); 10897c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen if (v != null) { 109076078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen ShortcutInfo info = (ShortcutInfo) v.getTag(); 109176078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen if (info != mCurrentDragInfo || includeCurrentDragItem) { 109276078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen mItemsInReadingOrder.add(v); 109376078c4ef35b6e95fb6d8129a32cf52a36625e28Adam Cohen } 10947c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 10957c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 10967c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 10977c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen mItemsInvalidated = false; 10987c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 10997c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen return mItemsInReadingOrder; 11007c6932140dcbd2db88d7a809ba72ee04abb5bf26Adam Cohen } 11018dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen 11028dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen public void getLocationInDragLayer(int[] loc) { 11038dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen mLauncher.getDragLayer().getLocationInDragLayer(this, loc); 11048dfcba4af7a7ece09e8c7d96053e54f3a383e905Adam Cohen } 1105ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen 1106ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen public void onFocusChange(View v, boolean hasFocus) { 1107ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen if (v == mFolderName && hasFocus) { 1108ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen startEditingFolderName(); 1109ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen } 1110ea0818d475df26d498ce08105bc2bc5582fce5a9Adam Cohen } 111131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 1112