diff options
Diffstat (limited to 'src/com/android/launcher2/Folder.java')
-rw-r--r-- | src/com/android/launcher2/Folder.java | 694 |
1 files changed, 644 insertions, 50 deletions
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java index 059e73d8b..d81183c6b 100644 --- a/src/com/android/launcher2/Folder.java +++ b/src/com/android/launcher2/Folder.java @@ -16,40 +16,80 @@ package com.android.launcher2; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +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; +import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; -import android.widget.AbsListView; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.Button; import android.widget.LinearLayout; +import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import com.android.launcher.R; +import com.android.launcher2.FolderInfo.FolderListener; + +import java.util.ArrayList; /** * Represents a set of icons chosen by the user or generated by the system. */ public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener, - OnItemClickListener, OnClickListener, View.OnLongClickListener { + OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget, FolderListener { - protected AbsListView mContent; protected DragController mDragController; - + protected Launcher mLauncher; - protected Button mCloseButton; - protected FolderInfo mInfo; - - /** - * Which item is being dragged - */ - protected ShortcutInfo mDragItem; + + private static final String TAG = "Launcher.Folder"; + + static final int STATE_NONE = -1; + static final int STATE_SMALL = 0; + static final int STATE_ANIMATING = 1; + static final int STATE_OPEN = 2; + + private int mExpandDuration; + protected CellLayout mContent; + private final LayoutInflater mInflater; + private final IconCache mIconCache; + private int mState = STATE_NONE; + 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; + private int mMaxCountX; + private int mMaxCountY; + private Rect mNewSize = new Rect(); + private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); + private Drawable mIconDrawable; + boolean mItemsInvalidated = false; + 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. @@ -60,21 +100,22 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL public Folder(Context context, AttributeSet attrs) { super(context, attrs); setAlwaysDrawnWithCacheEnabled(false); + mInflater = LayoutInflater.from(context); + mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache(); + mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration); + + mMaxCountX = LauncherModel.getCellCountX() - 1; + mMaxCountY = LauncherModel.getCellCountY() - 1; } @Override protected void onFinishInflate() { super.onFinishInflate(); - - mContent = (AbsListView) findViewById(R.id.folder_content); - mContent.setOnItemClickListener(this); - mContent.setOnItemLongClickListener(this); - - mCloseButton = (Button) findViewById(R.id.folder_close); - mCloseButton.setOnClickListener(this); - mCloseButton.setOnLongClickListener(this); + mContent = (CellLayout) findViewById(R.id.folder_content); + mContent.setGridSize(0, 0); + mContent.enableHardwareLayers(); } - + public void onItemClick(AdapterView parent, View v, int position, long id) { ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position); int[] pos = new int[2]; @@ -85,12 +126,54 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL } public void onClick(View v) { - mLauncher.closeFolder(this); + Object tag = v.getTag(); + if (tag instanceof ShortcutInfo) { + // refactor this code from Folder + ShortcutInfo item = (ShortcutInfo) tag; + int[] pos = new int[2]; + v.getLocationOnScreen(pos); + item.intent.setSourceBounds(new Rect(pos[0], pos[1], + pos[0] + v.getWidth(), pos[1] + v.getHeight())); + mLauncher.startActivitySafely(item.intent, item); + } } public boolean onLongClick(View v) { - mLauncher.closeFolder(this); - mLauncher.showRenameDialog(mInfo); + Object tag = v.getTag(); + if (tag instanceof ShortcutInfo) { + ShortcutInfo item = (ShortcutInfo) tag; + if (!v.isInTouchMode()) { + return false; + } + + mLauncher.getWorkspace().onDragStartedWithItem(v); + mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY); + mDragItemPosition[0] = item.cellX; + mDragItemPosition[1] = item.cellY; + mIconDrawable = ((TextView) v).getCompoundDrawables()[1]; + + mCurrentDragInfo = item; + mEmptyCell[0] = item.cellX; + mEmptyCell[1] = item.cellY; + mCurrentDragView = v; + mContent.removeView(mCurrentDragView); + mInfo.remove(item); + } else { + mLauncher.closeFolder(this); + mLauncher.showRenameDialog(mInfo); + } + return true; + } + + public Drawable getDragDrawable() { + return mIconDrawable; + } + + /** + * We need to handle touch events to prevent them from falling through to the workspace below. + */ + @Override + public boolean onTouchEvent(MotionEvent ev) { return true; } @@ -103,42 +186,24 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY); mLauncher.closeFolder(this); - mDragItem = app; - return true; } - @Override public void setDragController(DragController dragController) { mDragController = dragController; } - @Override - public void onDropCompleted(View target, Object dragInfo, boolean success) { - } - - @Override public void onDragViewVisible() { } - /** - * Sets the adapter used to populate the content area. The adapter must only - * contains ShortcutInfo items. - * - * @param adapter The list of applications to display in the folder. - */ - void setContentAdapter(BaseAdapter adapter) { - mContent.setAdapter(adapter); + void setLauncher(Launcher launcher) { + mLauncher = launcher; } - void notifyDataSetChanged() { - ((BaseAdapter) mContent.getAdapter()).notifyDataSetChanged(); + void setFolderIcon(FolderIcon icon) { + mFolderIcon = icon; } - void setLauncher(Launcher launcher) { - mLauncher = launcher; - } - /** * @return the FolderInfo object associated with this folder */ @@ -146,10 +211,12 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL return mInfo; } - // When the folder opens, we need to refresh the GridView's selection by - // forcing a layout void onOpen() { + // When the folder opens, we need to refresh the GridView's selection by + // forcing a layout + // TODO: find out if this is still necessary mContent.requestLayout(); + requestFocus(); } void onClose() { @@ -159,6 +226,533 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL void bind(FolderInfo info) { mInfo = info; - mCloseButton.setText(info.title); + ArrayList<ShortcutInfo> children = info.contents; + setupContentForNumItems(children.size()); + for (int i = 0; i < children.size(); i++) { + ShortcutInfo child = (ShortcutInfo) children.get(i); + createAndAddShortcut(child); + } + mItemsInvalidated = true; + mInfo.addListener(this); + } + + /** + * Creates a new UserFolder, inflated from R.layout.user_folder. + * + * @param context The application's context. + * + * @return A new UserFolder. + */ + static Folder fromXml(Context context) { + return (Folder) LayoutInflater.from(context).inflate(R.layout.user_folder, null); + } + + /** + * This method is intended to make the UserFolder to be visually identical in size and position + * to its associated FolderIcon. This allows for a seamless transition into the expanded state. + */ + private void positionAndSizeAsIcon() { + if (!(getParent() instanceof CellLayoutChildren)) return; + + CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams(); + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); + + if (mMode == PARTIAL_GROW) { + setScaleX(0.8f); + setScaleY(0.8f); + setAlpha(0f); + } else { + lp.width = iconLp.width; + lp.height = iconLp.height; + lp.x = iconLp.x; + lp.y = iconLp.y; + mContent.setAlpha(0); + } + mState = STATE_SMALL; + } + + public void animateOpen() { + if (mState != STATE_SMALL) { + positionAndSizeAsIcon(); + } + if (!(getParent() instanceof CellLayoutChildren)) return; + + ObjectAnimator oa; + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); + + centerAboutIcon(); + if (mMode == PARTIAL_GROW) { + PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1); + PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f); + PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f); + oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); + } else { + PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", mNewSize.width()); + PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", mNewSize.height()); + PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", mNewSize.left); + PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", mNewSize.top); + oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y); + oa.addUpdateListener(new AnimatorUpdateListener() { + public void onAnimationUpdate(ValueAnimator animation) { + requestLayout(); + } + }); + + PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f); + ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha); + alphaOa.setDuration(mExpandDuration); + alphaOa.setInterpolator(new AccelerateInterpolator(2.0f)); + alphaOa.start(); + } + + oa.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + mState = STATE_ANIMATING; + } + @Override + public void onAnimationEnd(Animator animation) { + mState = STATE_OPEN; + } + }); + oa.setDuration(mExpandDuration); + oa.start(); + } + + public void animateClosed() { + if (!(getParent() instanceof CellLayoutChildren)) return; + + CellLayoutChildren clc = (CellLayoutChildren) getParent(); + final CellLayout cellLayout = (CellLayout) clc.getParent(); + ObjectAnimator oa; + + if (mMode == PARTIAL_GROW) { + PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0); + PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f); + PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.9f); + oa = ObjectAnimator.ofPropertyValuesHolder(this, alpha, scaleX, scaleY); + } else { + CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams(); + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); + + PropertyValuesHolder width = PropertyValuesHolder.ofInt("width", iconLp.width); + PropertyValuesHolder height = PropertyValuesHolder.ofInt("height", iconLp.height); + PropertyValuesHolder x = PropertyValuesHolder.ofInt("x",iconLp.x); + PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", iconLp.y); + oa = ObjectAnimator.ofPropertyValuesHolder(lp, width, height, x, y); + oa.addUpdateListener(new AnimatorUpdateListener() { + public void onAnimationUpdate(ValueAnimator animation) { + requestLayout(); + } + }); + + PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f); + ObjectAnimator alphaOa = ObjectAnimator.ofPropertyValuesHolder(mContent, alpha); + alphaOa.setDuration(mExpandDuration); + alphaOa.setInterpolator(new DecelerateInterpolator(2.0f)); + alphaOa.start(); + } + + oa.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + onCloseComplete(); + cellLayout.removeViewWithoutMarkingCells(Folder.this); + mState = STATE_SMALL; + } + @Override + public void onAnimationStart(Animator animation) { + mState = STATE_ANIMATING; + } + }); + oa.setDuration(mExpandDuration); + oa.start(); + } + + void notifyDataSetChanged() { + // recreate all the children if the data set changes under us. We may want to do this more + // intelligently (ie just removing the views that should no longer exist) + mContent.removeAllViewsInLayout(); + bind(mInfo); + } + + public boolean acceptDrop(DragObject d) { + final ItemInfo item = (ItemInfo) d.dragInfo; + final int itemType = item.itemType; + return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || + itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) && + !isFull()); + } + + protected boolean findAndSetEmptyCells(ShortcutInfo item) { + int[] emptyCell = new int[2]; + if (mContent.findCellForSpan(emptyCell, item.spanX, item.spanY)) { + item.cellX = emptyCell[0]; + item.cellY = emptyCell[1]; + return true; + } else { + return false; + } + } + + protected void createAndAddShortcut(ShortcutInfo item) { + final TextView textView = + (TextView) mInflater.inflate(R.layout.application_boxed, this, false); + textView.setCompoundDrawablesWithIntrinsicBounds(null, + new FastBitmapDrawable(item.getIcon(mIconCache)), null, null); + textView.setText(item.title); + textView.setTag(item); + + textView.setOnClickListener(this); + textView.setOnLongClickListener(this); + + CellLayout.LayoutParams lp = + new CellLayout.LayoutParams(item.cellX, item.cellY, item.spanX, item.spanY); + boolean insert = false; + mContent.addViewToCellLayout(textView, insert ? 0 : -1, (int)item.id, lp, true); + } + + public void onDragEnter(DragObject d) { + mPreviousTargetCell[0] = -1; + mPreviousTargetCell[1] = -1; + mContent.onDragEnter(); + mOnExitAlarm.cancelAlarm(); + } + + 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; + } + } + + 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 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; + } + + OnAlarmListener mOnExitAlarmListener = new OnAlarmListener() { + public void onAlarm(Alarm alarm) { + mLauncher.closeFolder(Folder.this); + mCurrentDragInfo = null; + mCurrentDragView = null; + mSuppressOnAdd = false; + mRearrangeOnClose = true; + } + }; + + 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 + } + } + // TODO: if the drag fails, we need to re-add the item + } + } + + public boolean isDropEnabled() { + return true; + } + + public DropTarget getDropTargetDelegate(DragObject d) { + return null; + } + + private void setupContentDimension(int count) { + ArrayList<View> list = getItemsInReadingOrder(); + + int countX = mContent.getCountX(); + int countY = mContent.getCountY(); + boolean done = false; + + while (!done) { + int oldCountX = countX; + int oldCountY = countY; + if (countX * countY < count) { + // Current grid is too small, expand it + if (countX <= countY && countX < mMaxCountX) { + countX++; + } else if (countY < mMaxCountY) { + countY++; + } + if (countY == 0) countY++; + } else if ((countY - 1) * countX >= count && countY >= countX) { + countY = Math.max(0, countY - 1); + } else if ((countX - 1) * countY >= count) { + countX = Math.max(0, countX - 1); + } + done = countX == oldCountX && countY == oldCountY; + } + mContent.setGridSize(countX, countY); + arrangeChildren(list); + } + + public boolean isFull() { + return getItemCount() >= mMaxCountX * mMaxCountY; + } + + private void centerAboutIcon() { + CellLayout.LayoutParams iconLp = (CellLayout.LayoutParams) mFolderIcon.getLayoutParams(); + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); + + int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); + int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight(); + + int centerX = iconLp.x + iconLp.width / 2; + int centerY = iconLp.y + iconLp.height / 2; + int centeredLeft = centerX - width / 2; + int centeredTop = centerY - height / 2; + + CellLayoutChildren clc = (CellLayoutChildren) getParent(); + int parentWidth = 0; + int parentHeight = 0; + if (clc != null) { + parentWidth = clc.getMeasuredWidth(); + parentHeight = clc.getMeasuredHeight(); + } + + int left = Math.min(Math.max(0, centeredLeft), parentWidth - width); + int top = Math.min(Math.max(0, centeredTop), parentHeight - height); + + int folderPivotX = width / 2 + (centeredLeft - left); + int folderPivotY = height / 2 + (centeredTop - top); + setPivotX(folderPivotX); + setPivotY(folderPivotY); + int folderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() * + (1.0f * folderPivotX / width)); + int folderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() * + (1.0f * folderPivotY / height)); + mFolderIcon.setPivotX(folderIconPivotX); + mFolderIcon.setPivotY(folderIconPivotY); + + if (mMode == PARTIAL_GROW) { + lp.width = width; + lp.height = height; + lp.x = left; + lp.y = top; + } else { + mNewSize.set(left, top, left + width, top + height); + } + } + + private void setupContentForNumItems(int count) { + setupContentDimension(count); + + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); + if (lp == null) { + lp = new CellLayout.LayoutParams(0, 0, -1, -1); + lp.isLockedToGrid = false; + setLayoutParams(lp); + } + centerAboutIcon(); + } + + private void arrangeChildren(ArrayList<View> list) { + int[] vacant = new int[2]; + if (list == null) { + list = getItemsInReadingOrder(); + } + mContent.removeAllViews(); + + for (int i = 0; i < list.size(); i++) { + View v = list.get(i); + mContent.getVacantCell(vacant, 1, 1); + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) v.getLayoutParams(); + lp.cellX = vacant[0]; + lp.cellY = vacant[1]; + ItemInfo info = (ItemInfo) v.getTag(); + info.cellX = vacant[0]; + info.cellY = vacant[1]; + boolean insert = false; + mContent.addViewToCellLayout(v, insert ? 0 : -1, (int)info.id, lp, true); + LauncherModel.addOrMoveItemInDatabase(mLauncher, info, mInfo.id, 0, + info.cellX, info.cellY); + } + mItemsInvalidated = true; + } + + public int getItemCount() { + return mContent.getChildrenLayout().getChildCount(); + } + + public View getItemAt(int index) { + return mContent.getChildrenLayout().getChildAt(index); + } + + private void onCloseComplete() { + if (mRearrangeOnClose) { + setupContentForNumItems(getItemCount()); + mRearrangeOnClose = false; + } + } + + 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) { + mRearrangeOnClose = true; + } else { + setupContentForNumItems(getItemCount()); + } + } + + public void onItemsChanged() { + } + + public ArrayList<View> getItemsInReadingOrder() { + return getItemsInReadingOrder(true); + } + + public ArrayList<View> getItemsInReadingOrder(boolean includeCurrentDragItem) { + if (mItemsInvalidated) { + mItemsInReadingOrder.clear(); + for (int j = 0; j < mContent.getCountY(); j++) { + for (int i = 0; i < mContent.getCountX(); i++) { + View v = mContent.getChildAt(i, j); + if (v != null) { + ShortcutInfo info = (ShortcutInfo) v.getTag(); + if (info != mCurrentDragInfo || includeCurrentDragItem) { + mItemsInReadingOrder.add(v); + } + } + } + } + mItemsInvalidated = false; + } + return mItemsInReadingOrder; } } |