summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Cohen <adamcohen@google.com>2013-06-06 21:27:03 -0700
committerAdam Cohen <adamcohen@google.com>2013-06-06 21:28:57 -0700
commitf0f4eda31841f41d892bf18847c1acdc45d2cd64 (patch)
tree591b09ebbd03d34bf8a60e99cf60c4f5a32f9620
parente441bbc7d2baee03e96897b80f55db5ce2aa7e1f (diff)
downloadandroid_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.xml33
-rw-r--r--res/values-land/config.xml8
-rw-r--r--res/values-sw600dp-land/config.xml9
-rw-r--r--res/values-sw600dp/config.xml10
-rw-r--r--res/values-sw720dp/config.xml8
-rw-r--r--res/values/config.xml7
-rw-r--r--src/com/android/launcher3/CellLayout.java18
-rw-r--r--src/com/android/launcher3/Folder.java161
-rw-r--r--src/com/android/launcher3/LauncherModel.java144
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,