diff options
author | Adam Cohen <adamcohen@google.com> | 2013-06-06 21:27:03 -0700 |
---|---|---|
committer | Adam Cohen <adamcohen@google.com> | 2013-06-06 21:28:57 -0700 |
commit | f0f4eda31841f41d892bf18847c1acdc45d2cd64 (patch) | |
tree | 591b09ebbd03d34bf8a60e99cf60c4f5a32f9620 | |
parent | e441bbc7d2baee03e96897b80f55db5ce2aa7e1f (diff) | |
download | android_packages_apps_Trebuchet-f0f4eda31841f41d892bf18847c1acdc45d2cd64.tar.gz android_packages_apps_Trebuchet-f0f4eda31841f41d892bf18847c1acdc45d2cd64.tar.bz2 android_packages_apps_Trebuchet-f0f4eda31841f41d892bf18847c1acdc45d2cd64.zip |
Making folders scrollable
Change-Id: Id6c9ec62acc6d86dc627d20abad3e2d92010f539
-rw-r--r-- | res/layout/user_folder.xml | 33 | ||||
-rw-r--r-- | res/values-land/config.xml | 8 | ||||
-rw-r--r-- | res/values-sw600dp-land/config.xml | 9 | ||||
-rw-r--r-- | res/values-sw600dp/config.xml | 10 | ||||
-rw-r--r-- | res/values-sw720dp/config.xml | 8 | ||||
-rw-r--r-- | res/values/config.xml | 7 | ||||
-rw-r--r-- | src/com/android/launcher3/CellLayout.java | 18 | ||||
-rw-r--r-- | src/com/android/launcher3/Folder.java | 161 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherModel.java | 144 |
9 files changed, 308 insertions, 90 deletions
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml index 8c72dd673..3eeec35a2 100644 --- a/res/layout/user_folder.xml +++ b/res/layout/user_folder.xml @@ -22,20 +22,25 @@ android:orientation="vertical" android:background="@drawable/portal_container_holo"> - <com.android.launcher3.CellLayout - android:id="@+id/folder_content" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:paddingStart="@dimen/folder_padding" - android:paddingEnd="@dimen/folder_padding" - android:paddingTop="@dimen/folder_padding" - android:paddingBottom="@dimen/folder_padding" - android:cacheColorHint="#ff333333" - android:hapticFeedbackEnabled="false" - launcher:widthGap="@dimen/folder_width_gap" - launcher:heightGap="@dimen/folder_height_gap" - launcher:cellWidth="@dimen/folder_cell_width" - launcher:cellHeight="@dimen/folder_cell_height" /> + <ScrollView + android:id="@+id/scroll_view" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <com.android.launcher3.CellLayout + android:id="@+id/folder_content" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingStart="@dimen/folder_padding" + android:paddingEnd="@dimen/folder_padding" + android:paddingTop="@dimen/folder_padding" + android:paddingBottom="@dimen/folder_padding" + android:cacheColorHint="#ff333333" + android:hapticFeedbackEnabled="false" + launcher:widthGap="@dimen/folder_width_gap" + launcher:heightGap="@dimen/folder_height_gap" + launcher:cellWidth="@dimen/folder_cell_width" + launcher:cellHeight="@dimen/folder_cell_height" /> + </ScrollView> <com.android.launcher3.FolderEditText android:id="@+id/folder_name" diff --git a/res/values-land/config.xml b/res/values-land/config.xml index fc20456c3..da9f9f982 100644 --- a/res/values-land/config.xml +++ b/res/values-land/config.xml @@ -21,8 +21,10 @@ <!-- Whether or not to fade the side pages --> <bool name="config_workspaceFadeAdjacentScreens">false</bool> - <!-- Folder max bounds and max number of items. - Note: folder_max_count_x * folder_max_count_y >= folder_max_num_items. --> + <!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y + >= folder_max_num_items. If any values are set to 0, the values will be determined automatically. + A value of -1 indicates unbounded --> <integer name="folder_max_count_x">6</integer> - <integer name="folder_max_count_y">3</integer> + <integer name="folder_max_count_y">-1</integer> + <integer name="folder_max_num_items">-1</integer> </resources> diff --git a/res/values-sw600dp-land/config.xml b/res/values-sw600dp-land/config.xml index 822ea8995..3e8a92b55 100644 --- a/res/values-sw600dp-land/config.xml +++ b/res/values-sw600dp-land/config.xml @@ -1,7 +1,8 @@ <resources> -<!-- Folders --> - <!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y - >= folder_max_num_items. When these are set to -1, they are automatically determined. --> +<!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y + >= folder_max_num_items. If any values are set to 0, the values will be determined automatically. + A value of -1 indicates unbounded --> <integer name="folder_max_count_x">8</integer> - <integer name="folder_max_count_y">5</integer> + <integer name="folder_max_count_y">-1</integer> + <integer name="folder_max_num_items">-1</integer> </resources> diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml index fe8827418..d657d4311 100644 --- a/res/values-sw600dp/config.xml +++ b/res/values-sw600dp/config.xml @@ -11,12 +11,12 @@ <!-- DragController --> <integer name="config_flingToDeleteMinVelocity">-1000</integer> -<!-- Folders --> - <!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y - >= folder_max_num_items. When these are set to -1, they are automatically determined. --> +<!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y + >= folder_max_num_items. If any values are set to 0, the values will be determined automatically. + A value of -1 indicates unbounded --> <integer name="folder_max_count_x">6</integer> - <integer name="folder_max_count_y">6</integer> - <integer name="folder_max_num_items">36</integer> + <integer name="folder_max_count_y">-1</integer> + <integer name="folder_max_num_items">-1</integer> <!-- Camera distance for the overscroll effect. We use a higher value here because the workspace screens run nearly flush to the edge of the screen--> diff --git a/res/values-sw720dp/config.xml b/res/values-sw720dp/config.xml index 7c8d3d2e0..03e5f9ce3 100644 --- a/res/values-sw720dp/config.xml +++ b/res/values-sw720dp/config.xml @@ -10,10 +10,10 @@ <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. --> <integer name="config_workspaceSpringLoadShrinkPercentage">90</integer> -<!-- Folders --> - <!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y - >= folder_max_num_items. When these are set to -1, they are automatically determined. --> - <integer name="folder_max_count_x">-1</integer> +<!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y + >= folder_max_num_items. If any values are set to 0, the values will be determined automatically. + A value of -1 indicates unbounded --> + <integer name="folder_max_count_x">0</integer> <integer name="folder_max_count_y">-1</integer> <integer name="folder_max_num_items">-1</integer> diff --git a/res/values/config.xml b/res/values/config.xml index 2c691a4ce..4aec434ce 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -70,10 +70,11 @@ <integer name="config_cameraDistance">6500</integer> <!-- Folder max bounds and max number of items. Note: folder_max_count_x * folder_max_count_y - >= folder_max_num_items. When these are set to -1, they are automatically determined. --> + >= folder_max_num_items. If any values are set to 0, the values will be determined automatically. + A value of -1 indicates unbounded --> <integer name="folder_max_count_x">4</integer> - <integer name="folder_max_count_y">4</integer> - <integer name="folder_max_num_items">16</integer> + <integer name="folder_max_count_y">-1</integer> + <integer name="folder_max_num_items">-1</integer> <integer name="cell_count_x">4</integer> <integer name="cell_count_y">4</integer> diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index 842037c31..e115e43f5 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -106,6 +106,10 @@ public class CellLayout extends ViewGroup { private Rect mForegroundRect; private int mForegroundPadding; + // These values allow a fixed measurement to be set on the CellLayout. + private int mFixedWidth = -1; + private int mFixedHeight = -1; + // If we're actively dragging something over this screen, mIsDragOverlapping is true private boolean mIsDragOverlapping = false; private final Point mDragCenter = new Point(); @@ -972,6 +976,11 @@ public class CellLayout extends ViewGroup { metrics.set(cellWidth, cellHeight, widthGap, heightGap); } + public void setFixedSize(int width, int height) { + mFixedWidth = width; + mFixedHeight = height; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); @@ -980,7 +989,12 @@ public class CellLayout extends ViewGroup { int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); - if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) { + int newWidth = widthSpecSize; + int newHeight = heightSpecSize; + if (mFixedWidth > 0 && mFixedHeight > 0) { + newWidth = mFixedWidth; + newHeight = mFixedHeight; + } else if (widthSpecMode == MeasureSpec.UNSPECIFIED || heightSpecMode == MeasureSpec.UNSPECIFIED) { throw new RuntimeException("CellLayout cannot have UNSPECIFIED dimensions"); } @@ -1002,8 +1016,6 @@ public class CellLayout extends ViewGroup { } // Initial values correspond to widthSpecMode == MeasureSpec.EXACTLY - int newWidth = widthSpecSize; - int newHeight = heightSpecSize; if (widthSpecMode == MeasureSpec.AT_MOST) { newWidth = getPaddingLeft() + getPaddingRight() + (mCountX * mCellWidth) + ((mCountX - 1) * mWidthGap); diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index a7b5c5c54..347a1d428 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -20,6 +20,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; +import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; import android.graphics.PointF; @@ -42,6 +43,7 @@ import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.LinearLayout; +import android.widget.ScrollView; import android.widget.TextView; import com.android.launcher3.R; @@ -70,15 +72,20 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private int mExpandDuration; protected CellLayout mContent; + private ScrollView mScrollView; private final LayoutInflater mInflater; private final IconCache mIconCache; private int mState = STATE_NONE; private static final int REORDER_ANIMATION_DURATION = 230; + private static final int REORDER_DELAY = 250; private static final int ON_EXIT_CLOSE_DELAY = 800; private boolean mRearrangeOnClose = false; private FolderIcon mFolderIcon; private int mMaxCountX; private int mMaxCountY; + private int mMaxVisibleX; + private int mMaxVisibleY; + private int mMaxContentAreaHeight = 0; private int mMaxNumItems; private ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); private Drawable mIconDrawable; @@ -101,12 +108,21 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private float mFolderIconPivotX; private float mFolderIconPivotY; + private static final int SCROLL_CUT_OFF_AMOUNT = 60; + private static final int SCROLL_BAND_HEIGHT = 110; + private boolean mIsEditingName = false; private InputMethodManager mInputMethodManager; private static String sDefaultFolderName; private static String sHintText; + private int DRAG_MODE_NONE = 0; + private int DRAG_MODE_REORDER = 1; + private int DRAG_MODE_SCROLL_UP = 2; + private int DRAG_MODE_SCROLL_DOWN = 3; + private int mDragMode = DRAG_MODE_NONE; + private boolean mDestroyed; /** @@ -122,13 +138,33 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache(); Resources res = getResources(); - mMaxCountX = res.getInteger(R.integer.folder_max_count_x); - mMaxCountY = res.getInteger(R.integer.folder_max_count_y); + mMaxCountX = mMaxVisibleX = res.getInteger(R.integer.folder_max_count_x); + mMaxCountY = mMaxVisibleY = res.getInteger(R.integer.folder_max_count_y); mMaxNumItems = res.getInteger(R.integer.folder_max_num_items); - if (mMaxCountX < 0 || mMaxCountY < 0 || mMaxNumItems < 0) { - mMaxCountX = LauncherModel.getCellCountX(); - mMaxCountY = LauncherModel.getCellCountY(); + + if (mMaxCountY == -1) { + // -2 indicates unlimited + mMaxCountY = Integer.MAX_VALUE; + mMaxVisibleX = LauncherModel.getCellCountX() + 1; + } + if (mMaxNumItems == -1) { + // -2 indicates unlimited + mMaxNumItems = Integer.MAX_VALUE; + mMaxVisibleY = LauncherModel.getCellCountY() + 1; + } + if (mMaxCountX == 0) { + mMaxCountX = mMaxVisibleX = LauncherModel.getCellCountX(); + mMaxVisibleX++; + } + if (mMaxCountY == 0) { + mMaxCountY = mMaxVisibleY = LauncherModel.getCellCountY(); + mMaxVisibleY++; + } + if (mMaxNumItems == 0) { mMaxNumItems = mMaxCountX * mMaxCountY; + if (mMaxNumItems < 0) { + mMaxNumItems = Integer.MAX_VALUE; + } } mInputMethodManager = (InputMethodManager) @@ -152,7 +188,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList @Override protected void onFinishInflate() { super.onFinishInflate(); + mScrollView = (ScrollView) findViewById(R.id.scroll_view); mContent = (CellLayout) findViewById(R.id.folder_content); + + // Beyond this height, the area scrolls + mContent.setGridSize(mMaxVisibleX, mMaxVisibleY); + mMaxContentAreaHeight = mContent.getDesiredHeight() - SCROLL_CUT_OFF_AMOUNT; + mContent.setGridSize(0, 0); mContent.getShortcutsAndWidgets().setMotionEventSplittingEnabled(false); mContent.setInvertIfRtl(true); @@ -617,19 +659,72 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } public void onDragOver(DragObject d) { + int scrollOffset = mScrollView.getScrollY(); + 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); + r[0] -= getPaddingLeft(); + r[1] -= getPaddingTop(); + + mTargetCell = mContent.findNearestArea((int) r[0], (int) r[1] + scrollOffset, + 1, 1, mTargetCell); if (isLayoutRtl()) { mTargetCell[0] = mContent.getCountX() - mTargetCell[0] - 1; } - if (mTargetCell[0] != mPreviousTargetCell[0] || mTargetCell[1] != mPreviousTargetCell[1]) { + if (r[1] < SCROLL_BAND_HEIGHT && mScrollView.getScrollY() > 0) { + // Scroll up + if (mDragMode != DRAG_MODE_SCROLL_UP) { + mDragMode = DRAG_MODE_SCROLL_UP; + scrollUp(); + } + mReorderAlarm.cancelAlarm(); + } else if (r[1] > (getFolderHeight() - SCROLL_BAND_HEIGHT) && mScrollView.getScrollY() < + (mContent.getMeasuredHeight() - mScrollView.getMeasuredHeight())) { + if (mDragMode != DRAG_MODE_SCROLL_DOWN) { + mDragMode = DRAG_MODE_SCROLL_DOWN; + scrollDown(); + } + mReorderAlarm.cancelAlarm(); + } else if (mTargetCell[0] != mPreviousTargetCell[0] || mTargetCell[1] != mPreviousTargetCell[1]) { mReorderAlarm.cancelAlarm(); mReorderAlarm.setOnAlarmListener(mReorderAlarmListener); - mReorderAlarm.setAlarm(150); + mReorderAlarm.setAlarm(REORDER_DELAY); mPreviousTargetCell[0] = mTargetCell[0]; mPreviousTargetCell[1] = mTargetCell[1]; + mDragMode = DRAG_MODE_REORDER; + } else { + mDragMode = DRAG_MODE_NONE; + } + } + + Runnable mScrollUpRunnable = new Runnable() { + @Override + public void run() { + scrollUp(); + } + }; + + Runnable mScrollDownRunnable = new Runnable() { + @Override + public void run() { + scrollDown(); + } + }; + + private void scrollUp() { + if (mDragMode == DRAG_MODE_SCROLL_UP) { + mScrollView.setScrollY(mScrollView.getScrollY() - 7); + invalidate(); + post(mScrollUpRunnable); + } + } + + private void scrollDown() { + if (mDragMode == DRAG_MODE_SCROLL_DOWN) { + mScrollView.setScrollY(mScrollView.getScrollY() + 7); + invalidate(); + post(mScrollDownRunnable); } } @@ -681,6 +776,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mOnExitAlarm.setAlarm(ON_EXIT_CLOSE_DELAY); } mReorderAlarm.cancelAlarm(); + mDragMode = DRAG_MODE_NONE; } public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete, @@ -704,7 +800,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList completeDragExit(); } } - mDeleteFolderOnDropCompleted = false; mDragInProgress = false; mItemAddedBackToSelfViaIcon = false; @@ -714,7 +809,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList // Reordering may have occured, and we need to save the new item locations. We do this once // at the end to prevent unnecessary database operations. - updateItemLocationsInDatabase(); + updateItemLocationsInDatabaseBatch(); } @Override @@ -741,6 +836,18 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } } + private void updateItemLocationsInDatabaseBatch() { + ArrayList<View> list = getItemsInReadingOrder(); + ArrayList<ItemInfo> items = new ArrayList<ItemInfo>(); + for (int i = 0; i < list.size(); i++) { + View v = list.get(i); + ItemInfo info = (ItemInfo) v.getTag(); + items.add(info); + } + + LauncherModel.moveItemsInDatabase(mLauncher, items, mInfo.id, 0); + } + public void notifyDrop() { if (mDragInProgress) { mItemAddedBackToSelfViaIcon = true; @@ -792,8 +899,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); - int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight() - + mFolderNameHeight; + int height = getFolderHeight(); DragLayer parent = (DragLayer) mLauncher.findViewById(R.id.drag_layer); float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect); @@ -862,18 +968,35 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList centerAboutIcon(); } - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); - int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight() + private int getFolderHeight() { + int contentAreaHeight = mContent.getDesiredHeight(); + if (contentAreaHeight >= mMaxContentAreaHeight) { + // Subtract a bit so the user can see that it's scrollable. + contentAreaHeight = mMaxContentAreaHeight; + } + int height = getPaddingTop() + getPaddingBottom() + contentAreaHeight + mFolderNameHeight; + return height; + } + + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int contentWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(), + int contentAreaHeight = mContent.getDesiredHeight(); + if (contentAreaHeight >= mMaxContentAreaHeight) { + // Subtract a bit so the user can see that it's scrollable. + contentAreaHeight = mMaxContentAreaHeight; + } + + int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); + int height = getFolderHeight(); + int contentAreaWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(), MeasureSpec.EXACTLY); - int contentHeightSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredHeight(), + int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(contentAreaHeight, MeasureSpec.EXACTLY); - mContent.measure(contentWidthSpec, contentHeightSpec); - mFolderName.measure(contentWidthSpec, + mContent.setFixedSize(mContent.getDesiredWidth(), mContent.getDesiredHeight()); + mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec); + mFolderName.measure(contentAreaWidthSpec, MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY)); setMeasuredDimension(width, height); } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 5459af21b..bbdff9e86 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -22,6 +22,7 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProviderClient; +import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -332,50 +333,83 @@ public class LauncherModel extends BroadcastReceiver { Runnable r = new Runnable() { public void run() { cr.update(uri, values, null, null); + updateItemArrays(item, itemId, stackTrace); + } + }; + runOnWorkerThread(r); + } - // Lock on mBgLock *after* the db operation - synchronized (sBgLock) { - checkItemInfoLocked(itemId, item, stackTrace); + static void updateItemsInDatabaseHelper(Context context, final ArrayList<ContentValues> valuesList, + final ArrayList<ItemInfo> items, final String callingFunction) { + final ContentResolver cr = context.getContentResolver(); - if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP && - item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) { - // Item is in a folder, make sure this folder exists - if (!sBgFolders.containsKey(item.container)) { - // An items container is being set to a that of an item which is not in - // the list of Folders. - String msg = "item: " + item + " container being set to: " + - item.container + ", not in the list of folders"; - Log.e(TAG, msg); - Launcher.dumpDebugLogsToConsole(); - } - } + final StackTraceElement[] stackTrace = new Throwable().getStackTrace(); + Runnable r = new Runnable() { + public void run() { + ArrayList<ContentProviderOperation> ops = + new ArrayList<ContentProviderOperation>(); + int count = items.size(); + for (int i = 0; i < count; i++) { + ItemInfo item = items.get(i); + final long itemId = item.id; + final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false); + ContentValues values = valuesList.get(i); + + ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build()); + updateItemArrays(item, itemId, stackTrace); - // Items are added/removed from the corresponding FolderInfo elsewhere, such - // as in Workspace.onDrop. Here, we just add/remove them from the list of items - // that are on the desktop, as appropriate - ItemInfo modelItem = sBgItemsIdMap.get(itemId); - if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP || - modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { - switch (modelItem.itemType) { - case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: - case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: - case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: - if (!sBgWorkspaceItems.contains(modelItem)) { - sBgWorkspaceItems.add(modelItem); - } - break; - default: - break; - } - } else { - sBgWorkspaceItems.remove(modelItem); - } + } + try { + cr.applyBatch(LauncherProvider.AUTHORITY, ops); + } catch (Exception e) { + e.printStackTrace(); } } }; runOnWorkerThread(r); } + static void updateItemArrays(ItemInfo item, long itemId, StackTraceElement[] stackTrace) { + // Lock on mBgLock *after* the db operation + synchronized (sBgLock) { + checkItemInfoLocked(itemId, item, stackTrace); + + if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP && + item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) { + // Item is in a folder, make sure this folder exists + if (!sBgFolders.containsKey(item.container)) { + // An items container is being set to a that of an item which is not in + // the list of Folders. + String msg = "item: " + item + " container being set to: " + + item.container + ", not in the list of folders"; + Log.e(TAG, msg); + Launcher.dumpDebugLogsToConsole(); + } + } + + // Items are added/removed from the corresponding FolderInfo elsewhere, such + // as in Workspace.onDrop. Here, we just add/remove them from the list of items + // that are on the desktop, as appropriate + ItemInfo modelItem = sBgItemsIdMap.get(itemId); + if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP || + modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { + switch (modelItem.itemType) { + case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: + case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: + case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: + if (!sBgWorkspaceItems.contains(modelItem)) { + sBgWorkspaceItems.add(modelItem); + } + break; + default: + break; + } + } else { + sBgWorkspaceItems.remove(modelItem); + } + } + } + public void flushWorkerThread() { mFlushingWorkerThread = true; Runnable waiter = new Runnable() { @@ -438,6 +472,46 @@ public class LauncherModel extends BroadcastReceiver { } /** + * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the + * cellX, cellY have already been updated on the ItemInfos. + */ + static void moveItemsInDatabase(Context context, final ArrayList<ItemInfo> items, + final long container, final int screen) { + + ArrayList<ContentValues> contentValues = new ArrayList<ContentValues>(); + int count = items.size(); + + for (int i = 0; i < count; i++) { + ItemInfo item = items.get(i); + String transaction = "DbDebug Modify item (" + item.title + ") in db, id: " + + item.id + " (" + item.container + ", " + item.screen + ", " + item.cellX + + ", " + item.cellY + ") --> " + "(" + container + ", " + screen + ", " + + item.cellX + ", " + item.cellY + ")"; + Launcher.sDumpLogs.add(transaction); + item.container = container; + + // We store hotseat items in canonical form which is this orientation invariant position + // in the hotseat + if (context instanceof Launcher && screen < 0 && + container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) { + item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(item.cellX, + item.cellY); + } else { + item.screen = screen; + } + + final ContentValues values = new ContentValues(); + values.put(LauncherSettings.Favorites.CONTAINER, item.container); + values.put(LauncherSettings.Favorites.CELLX, item.cellX); + values.put(LauncherSettings.Favorites.CELLY, item.cellY); + values.put(LauncherSettings.Favorites.SCREEN, item.screen); + + contentValues.add(values); + } + updateItemsInDatabaseHelper(context, contentValues, items, "moveItemInDatabase"); + } + + /** * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY> */ static void modifyItemInDatabase(Context context, final ItemInfo item, final long container, |