Making folders scrollable
Change-Id: Id6c9ec62acc6d86dc627d20abad3e2d92010f539
This commit is contained in:
+19
-14
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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-->
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
int contentWidthSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredWidth(),
|
||||
MeasureSpec.EXACTLY);
|
||||
int contentHeightSpec = MeasureSpec.makeMeasureSpec(mContent.getDesiredHeight(),
|
||||
MeasureSpec.EXACTLY);
|
||||
mContent.measure(contentWidthSpec, contentHeightSpec);
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
|
||||
mFolderName.measure(contentWidthSpec,
|
||||
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 contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(contentAreaHeight,
|
||||
MeasureSpec.EXACTLY);
|
||||
|
||||
mContent.setFixedSize(mContent.getDesiredWidth(), mContent.getDesiredHeight());
|
||||
mScrollView.measure(contentAreaWidthSpec, contentAreaHeightSpec);
|
||||
mFolderName.measure(contentAreaWidthSpec,
|
||||
MeasureSpec.makeMeasureSpec(mFolderNameHeight, MeasureSpec.EXACTLY));
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
|
||||
updateItemArrays(item, itemId, stackTrace);
|
||||
|
||||
}
|
||||
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() {
|
||||
@@ -437,6 +471,46 @@ public class LauncherModel extends BroadcastReceiver {
|
||||
updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user