diff options
author | Adam Cohen <adamcohen@google.com> | 2011-06-13 16:55:12 -0700 |
---|---|---|
committer | Adam Cohen <adamcohen@google.com> | 2011-06-13 16:55:12 -0700 |
commit | bfbfd26c627a18f8e1e3e6d0e53e78feab360203 (patch) | |
tree | 0f823f053dcd28e303d19733e73f8215e0598b3d /src/com/android/launcher2/Folder.java | |
parent | 61fa4197c4316bb0f9b05fcefb676f86197a2273 (diff) | |
download | android_packages_apps_Trebuchet-bfbfd26c627a18f8e1e3e6d0e53e78feab360203.tar.gz android_packages_apps_Trebuchet-bfbfd26c627a18f8e1e3e6d0e53e78feab360203.tar.bz2 android_packages_apps_Trebuchet-bfbfd26c627a18f8e1e3e6d0e53e78feab360203.zip |
Initial implementation of folder reordering
Change-Id: I9f700e71f46e3b91afa96742d9e3890d519c391d
Diffstat (limited to 'src/com/android/launcher2/Folder.java')
-rw-r--r-- | src/com/android/launcher2/Folder.java | 230 |
1 files changed, 164 insertions, 66 deletions
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java index d6be3072c..d81183c6b 100644 --- a/src/com/android/launcher2/Folder.java +++ b/src/com/android/launcher2/Folder.java @@ -23,6 +23,7 @@ import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; +import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; @@ -54,11 +55,6 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL protected Launcher mLauncher; protected FolderInfo mInfo; - - /** - * Which item is being dragged - */ - protected ShortcutInfo mDragItem; private static final String TAG = "Launcher.Folder"; @@ -75,6 +71,8 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL private int[] mDragItemPosition = new int[2]; private static final int FULL_GROW = 0; private static final int PARTIAL_GROW = 1; + private static final int REORDER_ANIMATION_DURATION = 230; + private static final int ON_EXIT_CLOSE_DELAY = 800; private int mMode = PARTIAL_GROW; private boolean mRearrangeOnClose = false; private FolderIcon mFolderIcon; @@ -84,7 +82,14 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); private Drawable mIconDrawable; boolean mItemsInvalidated = false; - ShortcutInfo mCurrentDragInfo; + private ShortcutInfo mCurrentDragInfo; + private View mCurrentDragView; + boolean mSuppressOnAdd = false; + private int[] mTargetCell = new int[2]; + private int[] mPreviousTargetCell = new int[2]; + private int[] mEmptyCell = new int[2]; + private Alarm mReorderAlarm = new Alarm(); + private Alarm mOnExitAlarm = new Alarm(); /** * Used to inflate the Workspace from XML. @@ -136,8 +141,6 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL public boolean onLongClick(View v) { Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { - mLauncher.closeFolder(this); - ShortcutInfo item = (ShortcutInfo) tag; if (!v.isInTouchMode()) { return false; @@ -150,10 +153,11 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL mIconDrawable = ((TextView) v).getCompoundDrawables()[1]; mCurrentDragInfo = item; - mItemsInvalidated = true; - mInfo.itemsChanged(); - - mDragItem = item; + mEmptyCell[0] = item.cellX; + mEmptyCell[1] = item.cellY; + mCurrentDragView = v; + mContent.removeView(mCurrentDragView); + mInfo.remove(item); } else { mLauncher.closeFolder(this); mLauncher.showRenameDialog(mInfo); @@ -182,8 +186,6 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY); mLauncher.closeFolder(this); - mDragItem = app; - return true; } @@ -382,25 +384,6 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL !isFull()); } - public void onDrop(DragObject d) { - ShortcutInfo item; - if (d.dragInfo instanceof ApplicationInfo) { - // Came from all apps -- make a copy - item = ((ApplicationInfo) d.dragInfo).makeShortcut(); - item.spanX = 1; - item.spanY = 1; - } else { - item = (ShortcutInfo) d.dragInfo; - } - - // Dragged from self onto self - if (item == mCurrentDragInfo) { - mInfo.remove(item); - } - - mInfo.add(item); - } - protected boolean findAndSetEmptyCells(ShortcutInfo item) { int[] emptyCell = new int[2]; if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) { @@ -430,46 +413,135 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL } public void onDragEnter(DragObject d) { + mPreviousTargetCell[0] = -1; + mPreviousTargetCell[1] = -1; mContent.onDragEnter(); + mOnExitAlarm.cancelAlarm(); } - public void onDragOver(DragObject d) { - float[] r = mapPointFromScreenToContent(d.x, d.y, null); - mContent.visualizeDropLocation(null, null, (int) r[0], (int) r[1], 1, 1); + OnAlarmListener mReorderAlarmListener = new OnAlarmListener() { + public void onAlarm(Alarm alarm) { + realTimeReorder(mEmptyCell, mTargetCell); + } + }; + + boolean readingOrderGreaterThan(int[] v1, int[] v2) { + if (v1[1] > v2[1] || (v1[1] == v2[1] && v1[0] > v2[0])) { + return true; + } else { + return false; + } } - public void onDragExit(DragObject d) { - mContent.onDragExit(); + private void realTimeReorder(int[] empty, int[] target) { + boolean wrap; + int startX; + int endX; + int startY; + if (readingOrderGreaterThan(target, empty)) { + wrap = empty[0] >= mContent.getCountX() - 1; + startY = wrap ? empty[1] + 1 : empty[1]; + for (int y = startY; y <= target[1]; y++) { + startX = y == empty[1] ? empty[0] + 1 : 0; + endX = y < target[1] ? mContent.getCountX() - 1 : target[0]; + for (int x = startX; x <= endX; x++) { + View v = mContent.getChildAt(x,y); + if (mContent.animateChildToPosition(v, empty[0], empty[1], + REORDER_ANIMATION_DURATION)) { + empty[0] = x; + empty[1] = y; + } + } + } + } else { + wrap = empty[0] == 0; + startY = wrap ? empty[1] - 1 : empty[1]; + for (int y = startY; y >= target[1]; y--) { + startX = y == empty[1] ? empty[0] - 1 : mContent.getCountX() - 1; + endX = y > target[1] ? 0 : target[0]; + for (int x = startX; x >= endX; x--) { + View v = mContent.getChildAt(x,y); + if (mContent.animateChildToPosition(v, empty[0], empty[1], + REORDER_ANIMATION_DURATION)) { + empty[0] = x; + empty[1] = y; + } + } + } + } } - public float[] mapPointFromScreenToContent(int x, int y, float[] r) { - if (r == null) { - r = new float[2]; + public void onDragOver(DragObject d) { + float[] r = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, null); + mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1], 1, 1, mTargetCell); + + if (mTargetCell[0] != mPreviousTargetCell[0] || mTargetCell[1] != mPreviousTargetCell[1]) { + mReorderAlarm.cancelAlarm(); + mReorderAlarm.setOnAlarmListener(mReorderAlarmListener); + mReorderAlarm.setAlarm(150); + mPreviousTargetCell[0] = mTargetCell[0]; + mPreviousTargetCell[1] = mTargetCell[1]; } + } + + // This is used to compute the visual center of the dragView. The idea is that + // the visual center represents the user's interpretation of where the item is, and hence + // is the appropriate point to use when determining drop location. + private float[] getDragViewVisualCenter(int x, int y, int xOffset, int yOffset, + DragView dragView, float[] recycle) { + float res[]; + if (recycle == null) { + res = new float[2]; + } else { + res = recycle; + } + + // These represent the visual top and left of drag view if a dragRect was provided. + // If a dragRect was not provided, then they correspond to the actual view left and + // top, as the dragRect is in that case taken to be the entire dragView. + // R.dimen.dragViewOffsetY. + int left = x - xOffset; + int top = y - yOffset; + + // In order to find the visual center, we shift by half the dragRect + res[0] = left + dragView.getDragRegion().width() / 2; + res[1] = top + dragView.getDragRegion().height() / 2; + + return res; + } - int[] screenLocation = new int[2]; - mContent.getLocationOnScreen(screenLocation); + OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() { + public void onAlarm(Alarm alarm) { + mLauncher.closeFolder(Folder.this); + mCurrentDragInfo = null; + mCurrentDragView = null; + mSuppressOnAdd = false; + mRearrangeOnClose = true; + } + }; - r[0] = x - screenLocation[0]; - r[1] = y - screenLocation[1]; - return r; + public void onDragExit(DragObject d) { + // We only close the folder if this is a true drag exit, ie. not because a drop + // has occurred above the folder. + if (!d.dragComplete) { + mOnExitAlarm.setOnAlarmListener(mOnExitAlarmListener); + mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY); + } + mReorderAlarm.cancelAlarm(); + mContent.onDragExit(); } public void onDropCompleted(View target, DragObject d, boolean success) { + mCurrentDragInfo = null; + mCurrentDragView = null; + mSuppressOnAdd = false; if (!success) { if (d.dragView != null) { if (target instanceof CellLayout) { // TODO: we should animate the item back to the folder in this case } } - mCurrentDragInfo = null; - mItemsInvalidated = true; - mInfo.itemsChanged(); - } else { - if (target != this) { - mInfo.remove(mCurrentDragInfo); - mCurrentDragInfo = null; - } + // TODO: if the drag fails, we need to re-add the item } } @@ -594,18 +666,6 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL mItemsInvalidated = true; } - public void onAdd(ShortcutInfo item) { - mItemsInvalidated = true; - if (!findAndSetEmptyCells(item)) { - // The current layout is full, can we expand it? - setupContentForNumItems(getItemCount() + 1); - findAndSetEmptyCells(item); - } - createAndAddShortcut(item); - LauncherModel.addOrMoveItemInDatabase( - mLauncher, item, mInfo.id, 0, item.cellX, item.cellY); - } - public int getItemCount() { return mContent.getChildrenLayout().getChildCount(); } @@ -621,8 +681,46 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL } } + public void onDrop(DragObject d) { + ShortcutInfo item; + if (d.dragInfo instanceof ApplicationInfo) { + // Came from all apps -- make a copy + item = ((ApplicationInfo) d.dragInfo).makeShortcut(); + item.spanX = 1; + item.spanY = 1; + } else { + item = (ShortcutInfo) d.dragInfo; + } + // Dragged from self onto self + if (item == mCurrentDragInfo) { + ShortcutInfo si = (ShortcutInfo) mCurrentDragView.getTag(); + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) mCurrentDragView.getLayoutParams(); + si.cellX = lp.cellX = mEmptyCell[0]; + si.cellX = lp.cellY = mEmptyCell[1]; + mContent.addViewToCellLayout(mCurrentDragView, -1, (int)item.id, lp, true); + mSuppressOnAdd = true; + mItemsInvalidated = true; + setupContentDimension(getItemCount()); + } + mInfo.add(item); + } + + public void onAdd(ShortcutInfo item) { + mItemsInvalidated = true; + if (mSuppressOnAdd) return; + if (!findAndSetEmptyCells(item)) { + // The current layout is full, can we expand it? + setupContentForNumItems(getItemCount() + 1); + findAndSetEmptyCells(item); + } + createAndAddShortcut(item); + LauncherModel.addOrMoveItemInDatabase( + mLauncher, item, mInfo.id, 0, item.cellX, item.cellY); + } + public void onRemove(ShortcutInfo item) { mItemsInvalidated = true; + if (item == mCurrentDragInfo) return; View v = mContent.getChildAt(mDragItemPosition[0], mDragItemPosition[1]); mContent.removeView(v); if (mState == STATE_ANIMATING) { |