summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/layout-land/launcher.xml5
-rw-r--r--res/layout-port/launcher.xml6
-rw-r--r--src/com/android/launcher3/CellLayout.java7
-rw-r--r--src/com/android/launcher3/Folder.java6
-rw-r--r--src/com/android/launcher3/Hotseat.java4
-rw-r--r--src/com/android/launcher3/InstallShortcutReceiver.java3
-rw-r--r--src/com/android/launcher3/ItemInfo.java8
-rw-r--r--src/com/android/launcher3/Launcher.java127
-rw-r--r--src/com/android/launcher3/LauncherModel.java283
-rw-r--r--src/com/android/launcher3/LauncherProvider.java124
-rw-r--r--src/com/android/launcher3/LauncherSettings.java20
-rw-r--r--src/com/android/launcher3/PagedView.java4
-rw-r--r--src/com/android/launcher3/ShortcutInfo.java2
-rw-r--r--src/com/android/launcher3/Workspace.java276
14 files changed, 609 insertions, 266 deletions
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 44c0c056d..5fe05dd67 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -46,11 +46,6 @@
launcher:scrollIndicatorPaddingLeft="@dimen/qsb_bar_height"
launcher:scrollIndicatorPaddingRight="@dimen/button_bar_height">
- <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
</com.android.launcher3.Workspace>
<include
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 0a20e88f9..2aec4e8c2 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -63,12 +63,6 @@
launcher:pageSpacing="@dimen/workspace_page_spacing"
launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">
-
- <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
</com.android.launcher3.Workspace>
<include layout="@layout/hotseat"
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index e115e43f5..35598a2f2 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -709,7 +709,10 @@ public class CellLayout extends ViewGroup {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mCellInfo.screen = ((ViewGroup) getParent()).indexOfChild(this);
+ if (getParent() instanceof Workspace) {
+ Workspace workspace = (Workspace) getParent();
+ mCellInfo.screenId = workspace.getIdForScreen(this);
+ }
}
public void setTagToCellInfoForPoint(int touchX, int touchY) {
@@ -3334,7 +3337,7 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
int cellY = -1;
int spanX;
int spanY;
- int screen;
+ long screenId;
long container;
@Override
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 7b15e9edf..9eafc2231 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -1066,7 +1066,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
Runnable onCompleteRunnable = new Runnable() {
@Override
public void run() {
- CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screen);
+ CellLayout cellLayout = mLauncher.getCellLayout(mInfo.container, mInfo.screenId);
View child = null;
// Move the item from the folder to the workspace, in the position of the folder
@@ -1075,7 +1075,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
child = mLauncher.createShortcut(R.layout.application, cellLayout,
finalItem);
LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
- mInfo.screen, mInfo.cellX, mInfo.cellY);
+ mInfo.screenId, mInfo.cellX, mInfo.cellY);
}
if (getItemCount() <= 1) {
// Remove the folder
@@ -1089,7 +1089,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
// We add the child after removing the folder to prevent both from existing at
// the same time in the CellLayout.
if (child != null) {
- mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screen,
+ mLauncher.getWorkspace().addInScreen(child, mInfo.container, mInfo.screenId,
mInfo.cellX, mInfo.cellY, mInfo.spanX, mInfo.spanY);
}
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 50f7efd20..93f39ff3b 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -122,10 +122,10 @@ public class Hotseat extends FrameLayout {
fi.spanX = 1;
fi.spanY = 1;
fi.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
- fi.screen = mAllAppsButtonRank;
+ fi.screenId = mAllAppsButtonRank;
fi.itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
fi.title = "All Apps";
- LauncherModel.addItemToDatabase(launcher, fi, fi.container, fi.screen, fi.cellX,
+ LauncherModel.addItemToDatabase(launcher, fi, fi.container, fi.screenId, fi.cellX,
fi.cellY, false);
FolderIcon folder = FolderIcon.fromXml(R.layout.folder_icon, launcher,
getLayout(), fi, iconCache);
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 07d68da35..d647d96a4 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -333,6 +333,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
return false;
}
+ // TODO: this needs to be updated to take a screenId instead of a screen index
private static boolean findEmptyCell(Context context, ArrayList<ItemInfo> items, int[] xy,
int screen) {
final int xCount = LauncherModel.getCellCountX();
@@ -344,7 +345,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
for (int i = 0; i < items.size(); ++i) {
item = items.get(i);
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (item.screen == screen) {
+ if (item.screenId == screen) {
cellX = item.cellX;
cellY = item.cellY;
spanX = item.spanX;
diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java
index fb4183423..1d7ebba95 100644
--- a/src/com/android/launcher3/ItemInfo.java
+++ b/src/com/android/launcher3/ItemInfo.java
@@ -55,7 +55,7 @@ class ItemInfo {
/**
* Iindicates the screen in which the shortcut appears.
*/
- int screen = -1;
+ long screenId = -1;
/**
* Indicates the X position of the associated cell.
@@ -111,7 +111,7 @@ class ItemInfo {
cellY = info.cellY;
spanX = info.spanX;
spanY = info.spanY;
- screen = info.screen;
+ screenId = info.screenId;
itemType = info.itemType;
container = info.container;
// tempdebug:
@@ -141,7 +141,7 @@ class ItemInfo {
void onAddToDatabase(ContentValues values) {
values.put(LauncherSettings.BaseLauncherColumns.ITEM_TYPE, itemType);
values.put(LauncherSettings.Favorites.CONTAINER, container);
- values.put(LauncherSettings.Favorites.SCREEN, screen);
+ values.put(LauncherSettings.Favorites.SCREEN, screenId);
values.put(LauncherSettings.Favorites.CELLX, cellX);
values.put(LauncherSettings.Favorites.CELLY, cellY);
values.put(LauncherSettings.Favorites.SPANX, spanX);
@@ -188,7 +188,7 @@ class ItemInfo {
@Override
public String toString() {
return "Item(id=" + this.id + " type=" + this.itemType + " container=" + this.container
- + " screen=" + screen + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
+ + " screen=" + screenId + " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX
+ " spanY=" + spanY + " dropPos=" + dropPos + ")";
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index be0168261..bfe0be3a3 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -295,7 +295,7 @@ public class Launcher extends Activity
// Holds the page that we need to animate to, and the icon views that we need to animate up
// when we scroll to that page on resume.
- private int mNewShortcutAnimatePage = -1;
+ private long mNewShortcutAnimateScreenId = -1;
private ArrayList<View> mNewShortcutAnimateViews = new ArrayList<View>();
private ImageView mFolderIconImageView;
private Bitmap mFolderIconBitmap;
@@ -324,7 +324,7 @@ public class Launcher extends Activity
int requestCode;
Intent intent;
long container;
- int screen;
+ long screenId;
int cellX;
int cellY;
}
@@ -592,20 +592,20 @@ public class Launcher extends Activity
boolean result = false;
switch (args.requestCode) {
case REQUEST_PICK_APPLICATION:
- completeAddApplication(args.intent, args.container, args.screen, args.cellX,
+ completeAddApplication(args.intent, args.container, args.screenId, args.cellX,
args.cellY);
break;
case REQUEST_PICK_SHORTCUT:
processShortcut(args.intent);
break;
case REQUEST_CREATE_SHORTCUT:
- completeAddShortcut(args.intent, args.container, args.screen, args.cellX,
+ completeAddShortcut(args.intent, args.container, args.screenId, args.cellX,
args.cellY);
result = true;
break;
case REQUEST_CREATE_APPWIDGET:
int appWidgetId = args.intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
- completeAddAppWidget(appWidgetId, args.container, args.screen, null, null);
+ completeAddAppWidget(appWidgetId, args.container, args.screenId, null, null);
result = true;
break;
case REQUEST_PICK_WALLPAPER:
@@ -661,7 +661,7 @@ public class Launcher extends Activity
args.requestCode = requestCode;
args.intent = data;
args.container = mPendingAddInfo.container;
- args.screen = mPendingAddInfo.screen;
+ args.screenId = mPendingAddInfo.screenId;
args.cellX = mPendingAddInfo.cellX;
args.cellY = mPendingAddInfo.cellY;
if (isWorkspaceLocked()) {
@@ -678,7 +678,7 @@ public class Launcher extends Activity
private void completeTwoStageWidgetDrop(final int resultCode, final int appWidgetId) {
CellLayout cellLayout =
- (CellLayout) mWorkspace.getChildAt(mPendingAddInfo.screen);
+ (CellLayout) mWorkspace.getScreenWithId(mPendingAddInfo.screenId);
Runnable onCompleteRunnable = null;
int animationType = 0;
@@ -692,7 +692,7 @@ public class Launcher extends Activity
@Override
public void run() {
completeAddAppWidget(appWidgetId, mPendingAddInfo.container,
- mPendingAddInfo.screen, layout, null);
+ mPendingAddInfo.screenId, layout, null);
exitSpringLoadedDragModeDelayed((resultCode != RESULT_CANCELED), false,
null);
}
@@ -826,22 +826,7 @@ public class Launcher extends Activity
// Add a fullscreen unpadded view to the workspace to the left all other screens.
public void addCustomContentToLeft(View customContent) {
- CellLayout customScreen = (CellLayout)
- getLayoutInflater().inflate(R.layout.workspace_custom_content, null);
-
- int spanX = customScreen.getCountX();
- int spanY = customScreen.getCountY();
-
- CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, spanX, spanY);
- lp.canReorder = false;
-
- customScreen.addViewToCellLayout(customContent, 0, 0, lp, true);
-
- mWorkspace.addView(customScreen, 0);
-
- // Ensure that the current page and default page are maintained.
- mWorkspace.incrementNumScreensToLeft();
- mWorkspace.setCurrentPage(mWorkspace.getCurrentPage() + 1);
+ mWorkspace.addCustomContentToLeft(customContent);
}
@Override
@@ -955,11 +940,11 @@ public class Launcher extends Activity
}
final long pendingAddContainer = savedState.getLong(RUNTIME_STATE_PENDING_ADD_CONTAINER, -1);
- final int pendingAddScreen = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SCREEN, -1);
+ final long pendingAddScreen = savedState.getLong(RUNTIME_STATE_PENDING_ADD_SCREEN, -1);
if (pendingAddContainer != ItemInfo.NO_ID && pendingAddScreen > -1) {
mPendingAddInfo.container = pendingAddContainer;
- mPendingAddInfo.screen = pendingAddScreen;
+ mPendingAddInfo.screenId = pendingAddScreen;
mPendingAddInfo.cellX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_X);
mPendingAddInfo.cellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y);
mPendingAddInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X);
@@ -969,7 +954,6 @@ public class Launcher extends Activity
mRestoring = true;
}
-
boolean renameFolder = savedState.getBoolean(RUNTIME_STATE_PENDING_FOLDER_RENAME, false);
if (renameFolder) {
long id = savedState.getLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID);
@@ -977,7 +961,6 @@ public class Launcher extends Activity
mRestoring = true;
}
-
// Restore the AppsCustomize tab
if (mAppsCustomizeTabHost != null) {
String curTab = savedState.getString("apps_customize_currentTab");
@@ -1088,9 +1071,9 @@ public class Launcher extends Activity
* @param data The intent describing the application.
* @param cellInfo The position on screen where to create the shortcut.
*/
- void completeAddApplication(Intent data, long container, int screen, int cellX, int cellY) {
+ void completeAddApplication(Intent data, long container, long screenId, int cellX, int cellY) {
final int[] cellXY = mTmpAddItemCellCoordinates;
- final CellLayout layout = getCellLayout(container, screen);
+ final CellLayout layout = getCellLayout(container, screenId);
// First we check if we already know the exact location where we want to add this item.
if (cellX >= 0 && cellY >= 0) {
@@ -1107,7 +1090,7 @@ public class Launcher extends Activity
info.setActivity(data.getComponent(), Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
info.container = ItemInfo.NO_ID;
- mWorkspace.addApplicationShortcut(info, layout, container, screen, cellXY[0], cellXY[1],
+ mWorkspace.addApplicationShortcut(info, layout, container, screenId, cellXY[0], cellXY[1],
isWorkspaceLocked(), cellX, cellY);
} else {
Log.e(TAG, "Couldn't find ActivityInfo for selected application: " + data);
@@ -1120,11 +1103,11 @@ public class Launcher extends Activity
* @param data The intent describing the shortcut.
* @param cellInfo The position on screen where to create the shortcut.
*/
- private void completeAddShortcut(Intent data, long container, int screen, int cellX,
+ private void completeAddShortcut(Intent data, long container, long screenId, int cellX,
int cellY) {
int[] cellXY = mTmpAddItemCellCoordinates;
int[] touchXY = mPendingAddInfo.dropPos;
- CellLayout layout = getCellLayout(container, screen);
+ CellLayout layout = getCellLayout(container, screenId);
boolean foundCellSpan = false;
@@ -1164,11 +1147,10 @@ public class Launcher extends Activity
return;
}
- int adjustedScreen = screen - getWorkspace().mNumPagesToLeft;
- LauncherModel.addItemToDatabase(this, info, container, adjustedScreen, cellXY[0], cellXY[1], false);
+ LauncherModel.addItemToDatabase(this, info, container, screenId, cellXY[0], cellXY[1], false);
if (!mRestoring) {
- mWorkspace.addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1,
+ mWorkspace.addInScreen(view, container, screenId, cellXY[0], cellXY[1], 1, 1,
isWorkspaceLocked());
}
}
@@ -1206,14 +1188,14 @@ public class Launcher extends Activity
* @param appWidgetId The app widget id
* @param cellInfo The position on screen where to create the widget.
*/
- private void completeAddAppWidget(final int appWidgetId, long container, int screen,
+ private void completeAddAppWidget(final int appWidgetId, long container, long screenId,
AppWidgetHostView hostView, AppWidgetProviderInfo appWidgetInfo) {
if (appWidgetInfo == null) {
appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
}
// Calculate the grid spans needed to fit this widget
- CellLayout layout = getCellLayout(container, screen);
+ CellLayout layout = getCellLayout(container, screenId);
int[] minSpanXY = getMinSpanForWidget(this, appWidgetInfo);
int[] spanXY = getSpanForWidget(this, appWidgetInfo);
@@ -1265,9 +1247,8 @@ public class Launcher extends Activity
launcherInfo.minSpanX = mPendingAddInfo.minSpanX;
launcherInfo.minSpanY = mPendingAddInfo.minSpanY;
- int adjustedScreen = screen - getWorkspace().mNumPagesToLeft;
LauncherModel.addItemToDatabase(this, launcherInfo,
- container, adjustedScreen, cellXY[0], cellXY[1], false);
+ container, screenId, cellXY[0], cellXY[1], false);
if (!mRestoring) {
if (hostView == null) {
@@ -1283,7 +1264,7 @@ public class Launcher extends Activity
launcherInfo.hostView.setVisibility(View.VISIBLE);
launcherInfo.notifyWidgetSizeChanged(this);
- mWorkspace.addInScreen(launcherInfo.hostView, container, screen, cellXY[0], cellXY[1],
+ mWorkspace.addInScreen(launcherInfo.hostView, container, screenId, cellXY[0], cellXY[1],
launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
addWidgetToAutoAdvanceIfNeeded(launcherInfo.hostView, appWidgetInfo);
@@ -1562,10 +1543,10 @@ public class Launcher extends Activity
// this state is reflected.
closeFolder();
- if (mPendingAddInfo.container != ItemInfo.NO_ID && mPendingAddInfo.screen > -1 &&
+ if (mPendingAddInfo.container != ItemInfo.NO_ID && mPendingAddInfo.screenId > -1 &&
mWaitingForResult) {
outState.putLong(RUNTIME_STATE_PENDING_ADD_CONTAINER, mPendingAddInfo.container);
- outState.putInt(RUNTIME_STATE_PENDING_ADD_SCREEN, mPendingAddInfo.screen);
+ outState.putLong(RUNTIME_STATE_PENDING_ADD_SCREEN, mPendingAddInfo.screenId);
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_X, mPendingAddInfo.cellX);
outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mPendingAddInfo.cellY);
outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_X, mPendingAddInfo.spanX);
@@ -1791,7 +1772,7 @@ public class Launcher extends Activity
private void resetAddInfo() {
mPendingAddInfo.container = ItemInfo.NO_ID;
- mPendingAddInfo.screen = -1;
+ mPendingAddInfo.screenId = -1;
mPendingAddInfo.cellX = mPendingAddInfo.cellY = -1;
mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1;
mPendingAddInfo.minSpanX = mPendingAddInfo.minSpanY = -1;
@@ -1810,7 +1791,7 @@ public class Launcher extends Activity
startActivityForResultSafely(intent, REQUEST_CREATE_APPWIDGET);
} else {
// Otherwise just add it
- completeAddAppWidget(appWidgetId, info.container, info.screen, boundWidget,
+ completeAddAppWidget(appWidgetId, info.container, info.screenId, boundWidget,
appWidgetInfo);
// Exit spring loaded mode if necessary after adding the widget
exitSpringLoadedDragModeDelayed(true, false, null);
@@ -1821,15 +1802,15 @@ public class Launcher extends Activity
* Process a shortcut drop.
*
* @param componentName The name of the component
- * @param screen The screen where it should be added
+ * @param screenId The ID of the screen where it should be added
* @param cell The cell it should be added to, optional
* @param position The location on the screen where it was dropped, optional
*/
- void processShortcutFromDrop(ComponentName componentName, long container, int screen,
+ void processShortcutFromDrop(ComponentName componentName, long container, long screenId,
int[] cell, int[] loc) {
resetAddInfo();
mPendingAddInfo.container = container;
- mPendingAddInfo.screen = screen;
+ mPendingAddInfo.screenId = screenId;
mPendingAddInfo.dropPos = loc;
if (cell != null) {
@@ -1846,15 +1827,15 @@ public class Launcher extends Activity
* Process a widget drop.
*
* @param info The PendingAppWidgetInfo of the widget being added.
- * @param screen The screen where it should be added
+ * @param screenId The ID of the screen where it should be added
* @param cell The cell it should be added to, optional
* @param position The location on the screen where it was dropped, optional
*/
- void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, int screen,
+ void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, long screenId,
int[] cell, int[] span, int[] loc) {
resetAddInfo();
mPendingAddInfo.container = info.container = container;
- mPendingAddInfo.screen = info.screen = screen;
+ mPendingAddInfo.screenId = info.screenId = screenId;
mPendingAddInfo.dropPos = loc;
mPendingAddInfo.minSpanX = info.minSpanX;
mPendingAddInfo.minSpanY = info.minSpanY;
@@ -1923,20 +1904,20 @@ public class Launcher extends Activity
startActivityForResult(intent, REQUEST_PICK_WALLPAPER);
}
- FolderIcon addFolder(CellLayout layout, long container, final int screen, int cellX,
+ FolderIcon addFolder(CellLayout layout, long container, final long screenId, int cellX,
int cellY) {
final FolderInfo folderInfo = new FolderInfo();
folderInfo.title = getText(R.string.folder_name);
// Update the model
- LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screen, cellX, cellY,
+ LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screenId, cellX, cellY,
false);
sFolders.put(folderInfo.id, folderInfo);
// Create the view
FolderIcon newFolder =
FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo, mIconCache);
- mWorkspace.addInScreen(newFolder, container, screen, cellX, cellY, 1, 1,
+ mWorkspace.addInScreen(newFolder, container, screenId, cellX, cellY, 1, 1,
isWorkspaceLocked());
return newFolder;
}
@@ -2233,7 +2214,7 @@ public class Launcher extends Activity
// it is actually opened. There have been a few instances where this gets out of sync.
if (info.opened && openFolder == null) {
Log.d(TAG, "Folder info marked as open, but associated folder is not open. Screen: "
- + info.screen + " (" + info.cellX + ", " + info.cellY + ")");
+ + info.screenId + " (" + info.cellX + ", " + info.cellY + ")");
info.opened = false;
}
@@ -2471,7 +2452,7 @@ public class Launcher extends Activity
/**
* Returns the CellLayout of the specified container at the specified screen.
*/
- CellLayout getCellLayout(long container, int screen) {
+ CellLayout getCellLayout(long container, long screenId) {
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
if (mHotseat != null) {
return mHotseat.getLayout();
@@ -2479,7 +2460,7 @@ public class Launcher extends Activity
return null;
}
} else {
- return (CellLayout) mWorkspace.getChildAt(screen);
+ return (CellLayout) mWorkspace.getScreenWithId(screenId);
}
}
@@ -3442,7 +3423,7 @@ public class Launcher extends Activity
mOnResumeCallbacks.clear();
final Workspace workspace = mWorkspace;
- mNewShortcutAnimatePage = -1;
+ mNewShortcutAnimateScreenId = -1;
mNewShortcutAnimateViews.clear();
mWorkspace.clearDropTargets();
int count = workspace.getChildCount();
@@ -3457,6 +3438,15 @@ public class Launcher extends Activity
}
}
+ @Override
+ public void bindScreens(ArrayList<Long> orderedScreenIds) {
+ int count = orderedScreenIds.size();
+ for (int i = 0; i < count; i++) {
+ mWorkspace.insertNewWorkspaceScreenOnBind(orderedScreenIds.get(i));
+ }
+ mWorkspace.addExtraEmptyScreen();
+ }
+
/**
* Bind the items start-end from the list.
*
@@ -3491,8 +3481,9 @@ public class Launcher extends Activity
ShortcutInfo info = (ShortcutInfo) item;
String uri = info.intent.toUri(0).toString();
View shortcut = createShortcut(info);
- workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
- item.cellY, 1, 1, false);
+
+ workspace.addInScreenFromBind(shortcut, item.container, item.screenId, item.cellX,
+ item.cellY, 1, 1);
boolean animateIconUp = false;
synchronized (newApps) {
if (newApps.contains(uri)) {
@@ -3504,7 +3495,7 @@ public class Launcher extends Activity
shortcut.setAlpha(0f);
shortcut.setScaleX(0f);
shortcut.setScaleY(0f);
- mNewShortcutAnimatePage = item.screen;
+ mNewShortcutAnimateScreenId = item.screenId;
if (!mNewShortcutAnimateViews.contains(shortcut)) {
mNewShortcutAnimateViews.add(shortcut);
}
@@ -3514,8 +3505,8 @@ public class Launcher extends Activity
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
(ViewGroup) workspace.getChildAt(workspace.getCurrentPage()),
(FolderInfo) item, mIconCache);
- workspace.addInScreen(newFolder, item.container, item.screen, item.cellX,
- item.cellY, 1, 1, false);
+ workspace.addInScreenFromBind(newFolder, item.container, item.screenId, item.cellX,
+ item.cellY, 1, 1);
break;
}
}
@@ -3569,7 +3560,7 @@ public class Launcher extends Activity
item.hostView.setTag(item);
item.onBindAppWidget(this);
- workspace.addInScreen(item.hostView, item.container, item.screen, item.cellX,
+ workspace.addInScreen(item.hostView, item.container, item.screenId, item.cellX,
item.cellY, item.spanX, item.spanY, false);
addWidgetToAutoAdvanceIfNeeded(item.hostView, appWidgetInfo);
@@ -3627,13 +3618,13 @@ public class Launcher extends Activity
}
};
- boolean willSnapPage = mNewShortcutAnimatePage > -1 &&
- mNewShortcutAnimatePage != mWorkspace.getCurrentPage();
+ boolean willSnapPage = mNewShortcutAnimateScreenId > -1 &&
+ mNewShortcutAnimateScreenId != mWorkspace.getCurrentPage();
if (canRunNewAppsAnimation()) {
// If the user has not interacted recently, then either snap to the new page to show
// the new-apps animation or just run them if they are to appear on the current page
if (willSnapPage) {
- mWorkspace.snapToPage(mNewShortcutAnimatePage, newAppsRunnable);
+ mWorkspace.snapToScreenId(mNewShortcutAnimateScreenId, newAppsRunnable);
} else {
runNewAppsAnimation(false);
}
@@ -3717,7 +3708,7 @@ public class Launcher extends Activity
}
// Clean up
- mNewShortcutAnimatePage = -1;
+ mNewShortcutAnimateScreenId = -1;
mNewShortcutAnimateViews.clear();
new Thread("clearNewAppsThread") {
public void run() {
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 2e76a6506..041882fd9 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -48,14 +48,13 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
-import com.android.launcher3.R;
import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
import java.text.Collator;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -63,6 +62,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.TreeMap;
/**
* Maintains in-memory state of the Launcher. It is expected that there should be only one
@@ -138,6 +138,10 @@ public class LauncherModel extends BroadcastReceiver {
// sBgDbIconCache is the set of ItemInfos that need to have their icons updated in the database
static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();
+
+ // sBgWorkspaceScreens is the ordered set of workspace screens.
+ static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
+
// </ only access in worker thread >
private IconCache mIconCache;
@@ -153,6 +157,7 @@ public class LauncherModel extends BroadcastReceiver {
public int getCurrentWorkspaceScreen();
public void startBinding();
public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end);
+ public void bindScreens(ArrayList<Long> orderedScreenIds);
public void bindFolders(HashMap<Long,FolderInfo> folders);
public void finishBindingItems(boolean upgradePath);
public void bindAppWidget(LauncherAppWidgetInfo info);
@@ -257,13 +262,13 @@ public class LauncherModel extends BroadcastReceiver {
* <container, screen, cellX, cellY>
*/
static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,
- int screen, int cellX, int cellY) {
+ long screenId, int cellX, int cellY) {
if (item.container == ItemInfo.NO_ID) {
// From all apps
- addItemToDatabase(context, item, container, screen, cellX, cellY, false);
+ addItemToDatabase(context, item, container, screenId, cellX, cellY, false);
} else {
// From somewhere else
- moveItemInDatabase(context, item, container, screen, cellX, cellY);
+ moveItemInDatabase(context, item, container, screenId, cellX, cellY);
}
}
@@ -280,7 +285,7 @@ public class LauncherModel extends BroadcastReceiver {
modelShortcut.id == shortcut.id &&
modelShortcut.itemType == shortcut.itemType &&
modelShortcut.container == shortcut.container &&
- modelShortcut.screen == shortcut.screen &&
+ modelShortcut.screenId == shortcut.screenId &&
modelShortcut.cellX == shortcut.cellX &&
modelShortcut.cellY == shortcut.cellY &&
modelShortcut.spanX == shortcut.spanX &&
@@ -444,10 +449,10 @@ public class LauncherModel extends BroadcastReceiver {
* Move an item in the DB to a new <container, screen, cellX, cellY>
*/
static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
- final int screen, final int cellX, final int cellY) {
+ final long screenId, final int cellX, final int cellY) {
String transaction = "DbDebug Modify item (" + item.title + ") in db, id: " + item.id +
- " (" + item.container + ", " + item.screen + ", " + item.cellX + ", " + item.cellY +
- ") --> " + "(" + container + ", " + screen + ", " + cellX + ", " + cellY + ")";
+ " (" + item.container + ", " + item.screenId + ", " + item.cellX + ", " + item.cellY +
+ ") --> " + "(" + container + ", " + screenId + ", " + cellX + ", " + cellY + ")";
Launcher.sDumpLogs.add(transaction);
Log.d(TAG, transaction);
item.container = container;
@@ -456,18 +461,18 @@ public class LauncherModel extends BroadcastReceiver {
// We store hotseat items in canonical form which is this orientation invariant position
// in the hotseat
- if (context instanceof Launcher && screen < 0 &&
+ if (context instanceof Launcher && screenId < 0 &&
container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
+ item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
} else {
- item.screen = screen;
+ item.screenId = screenId;
}
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);
+ values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");
}
@@ -485,7 +490,7 @@ public class LauncherModel extends BroadcastReceiver {
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.id + " (" + item.container + ", " + item.screenId + ", " + item.cellX
+ ", " + item.cellY + ") --> " + "(" + container + ", " + screen + ", "
+ item.cellX + ", " + item.cellY + ")";
Launcher.sDumpLogs.add(transaction);
@@ -495,17 +500,17 @@ public class LauncherModel extends BroadcastReceiver {
// in the hotseat
if (context instanceof Launcher && screen < 0 &&
container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(item.cellX,
+ item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(item.cellX,
item.cellY);
} else {
- item.screen = screen;
+ item.screenId = 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);
+ values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
contentValues.add(values);
}
@@ -516,10 +521,10 @@ public class LauncherModel extends BroadcastReceiver {
* 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,
- final int screen, final int cellX, final int cellY, final int spanX, final int spanY) {
+ final long screenId, final int cellX, final int cellY, final int spanX, final int spanY) {
String transaction = "DbDebug Modify item (" + item.title + ") in db, id: " + item.id +
- " (" + item.container + ", " + item.screen + ", " + item.cellX + ", " + item.cellY +
- ") --> " + "(" + container + ", " + screen + ", " + cellX + ", " + cellY + ")";
+ " (" + item.container + ", " + item.screenId + ", " + item.cellX + ", " + item.cellY +
+ ") --> " + "(" + container + ", " + screenId + ", " + cellX + ", " + cellY + ")";
Launcher.sDumpLogs.add(transaction);
Log.d(TAG, transaction);
item.cellX = cellX;
@@ -529,11 +534,11 @@ public class LauncherModel extends BroadcastReceiver {
// We store hotseat items in canonical form which is this orientation invariant position
// in the hotseat
- if (context instanceof Launcher && screen < 0 &&
+ if (context instanceof Launcher && screenId < 0 &&
container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
+ item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
} else {
- item.screen = screen;
+ item.screenId = screenId;
}
final ContentValues values = new ContentValues();
@@ -542,7 +547,7 @@ public class LauncherModel extends BroadcastReceiver {
values.put(LauncherSettings.Favorites.CELLY, item.cellY);
values.put(LauncherSettings.Favorites.SPANX, item.spanX);
values.put(LauncherSettings.Favorites.SPANY, item.spanY);
- values.put(LauncherSettings.Favorites.SCREEN, item.screen);
+ values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");
}
@@ -604,7 +609,7 @@ public class LauncherModel extends BroadcastReceiver {
item.spanY = c.getInt(spanYIndex);
item.container = c.getInt(containerIndex);
item.itemType = c.getInt(itemTypeIndex);
- item.screen = c.getInt(screenIndex);
+ item.screenId = c.getInt(screenIndex);
items.add(item);
}
@@ -646,7 +651,7 @@ public class LauncherModel extends BroadcastReceiver {
folderInfo.title = c.getString(titleIndex);
folderInfo.id = id;
folderInfo.container = c.getInt(containerIndex);
- folderInfo.screen = c.getInt(screenIndex);
+ folderInfo.screenId = c.getInt(screenIndex);
folderInfo.cellX = c.getInt(cellXIndex);
folderInfo.cellY = c.getInt(cellYIndex);
@@ -664,17 +669,17 @@ public class LauncherModel extends BroadcastReceiver {
* cellY fields of the item. Also assigns an ID to the item.
*/
static void addItemToDatabase(Context context, final ItemInfo item, final long container,
- final int screen, final int cellX, final int cellY, final boolean notify) {
+ final long screenId, final int cellX, final int cellY, final boolean notify) {
item.container = container;
item.cellX = cellX;
item.cellY = cellY;
// We store hotseat items in canonical form which is this orientation invariant position
// in the hotseat
- if (context instanceof Launcher && screen < 0 &&
+ if (context instanceof Launcher && screenId < 0 &&
container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- item.screen = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
+ item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
} else {
- item.screen = screen;
+ item.screenId = screenId;
}
final ContentValues values = new ContentValues();
@@ -682,14 +687,14 @@ public class LauncherModel extends BroadcastReceiver {
item.onAddToDatabase(values);
LauncherAppState app = LauncherAppState.getInstance();
- item.id = app.getLauncherProvider().generateNewId();
+ item.id = app.getLauncherProvider().generateNewItemId();
values.put(LauncherSettings.Favorites._ID, item.id);
item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
Runnable r = new Runnable() {
public void run() {
String transaction = "DbDebug Add item (" + item.title + ") to db, id: "
- + item.id + " (" + container + ", " + screen + ", " + cellX + ", "
+ + item.id + " (" + container + ", " + screenId + ", " + cellX + ", "
+ cellY + ")";
Launcher.sDumpLogs.add(transaction);
Log.d(TAG, transaction);
@@ -734,9 +739,9 @@ public class LauncherModel extends BroadcastReceiver {
* Creates a new unique child id, for a given cell span across all layouts.
*/
static int getCellLayoutChildId(
- long container, int screen, int localCellX, int localCellY, int spanX, int spanY) {
+ long container, long screen, int localCellX, int localCellY, int spanX, int spanY) {
return (((int) container & 0xFF) << 24)
- | (screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
+ | ((int) screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
}
static int getCellCountX() {
@@ -768,7 +773,7 @@ public class LauncherModel extends BroadcastReceiver {
Runnable r = new Runnable() {
public void run() {
String transaction = "DbDebug Delete item (" + item.title + ") from db, id: "
- + item.id + " (" + item.container + ", " + item.screen + ", " + item.cellX +
+ + item.id + " (" + item.container + ", " + item.screenId + ", " + item.cellX +
", " + item.cellY + ")";
Launcher.sDumpLogs.add(transaction);
Log.d(TAG, transaction);
@@ -809,6 +814,48 @@ public class LauncherModel extends BroadcastReceiver {
}
/**
+ * Update the order of the workspace screens in the database. The array list contains
+ * a list of screen ids in the order that they should appear.
+ */
+ static void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {
+ final ContentResolver cr = context.getContentResolver();
+ final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
+
+ // Remove any negative screen ids -- these aren't persisted
+ Iterator<Long> iter = screens.iterator();
+ while (iter.hasNext()) {
+ long id = iter.next();
+ if (id < 0) {
+ iter.remove();
+ }
+ }
+
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ final ArrayList<Long> screensCopy = new ArrayList<Long>();
+
+ // Clear the table
+ cr.delete(uri, null, null);
+ int count = screens.size();
+ ContentValues[] values = new ContentValues[count];
+ for (int i = 0; i < count; i++) {
+ ContentValues v = new ContentValues();
+ long screenId = screens.get(i);
+ v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
+ v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
+ screensCopy.add(screenId);
+ values[i] = v;
+ }
+ cr.bulkInsert(uri, values);
+ sBgWorkspaceScreens.clear();
+ sBgWorkspaceScreens.addAll(screensCopy);
+ }
+ };
+ runOnWorkerThread(r);
+ }
+
+ /**
* Remove the contents of the specified folder from the database
*/
static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
@@ -1219,7 +1266,6 @@ public class LauncherModel extends BroadcastReceiver {
}
}
-
// Update the saved icons if necessary
if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");
synchronized (sBgLock) {
@@ -1280,23 +1326,23 @@ public class LauncherModel extends BroadcastReceiver {
}
// check & update map of what's occupied; used to discard overlapping/invalid items
- private boolean checkItemPlacement(ItemInfo occupied[][][], ItemInfo item) {
- int containerIndex = item.screen;
+ private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item) {
+ long containerIndex = item.screenId;
if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- // Return early if we detect that an item is under the hotseat button
- if (mCallbacks == null || mCallbacks.get().isAllAppsButtonRank(item.screen)) {
- return false;
- }
-
- // We use the last index to refer to the hotseat and the screen as the rank, so
- // test and update the occupied state accordingly
- if (occupied[Launcher.SCREEN_COUNT][item.screen][0] != null) {
- Log.e(TAG, "Error loading shortcut into hotseat " + item
- + " into position (" + item.screen + ":" + item.cellX + "," + item.cellY
- + ") occupied by " + occupied[Launcher.SCREEN_COUNT][item.screen][0]);
- return false;
+ if (occupied.containsKey(LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {
+ if (occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)
+ [(int) item.screenId][0] != null) {
+ Log.e(TAG, "Error loading shortcut into hotseat " + item
+ + " into position (" + item.screenId + ":" + item.cellX + ","
+ + item.cellY + ") occupied by "
+ + occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)
+ [(int) item.screenId][0]);
+ return false;
+ }
} else {
- occupied[Launcher.SCREEN_COUNT][item.screen][0] = item;
+ ItemInfo[][] items = new ItemInfo[mCellCountX + 1][mCellCountY + 1];
+ items[(int) item.screenId][0] = item;
+ occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);
return true;
}
} else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
@@ -1304,22 +1350,28 @@ public class LauncherModel extends BroadcastReceiver {
return true;
}
+ if (!occupied.containsKey(item.screenId)) {
+ ItemInfo[][] items = new ItemInfo[mCellCountX + 1][mCellCountY + 1];
+ occupied.put(item.screenId, items);
+ }
+
+ ItemInfo[][] screens = occupied.get(item.screenId);
// Check if any workspace icons overlap with each other
for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
- if (occupied[containerIndex][x][y] != null) {
+ if (screens[x][y] != null) {
Log.e(TAG, "Error loading shortcut " + item
- + " into cell (" + containerIndex + "-" + item.screen + ":"
+ + " into cell (" + containerIndex + "-" + item.screenId + ":"
+ x + "," + y
+ ") occupied by "
- + occupied[containerIndex][x][y]);
+ + screens[x][y]);
return false;
}
}
}
for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
- occupied[containerIndex][x][y] = item;
+ screens[x][y] = item;
}
}
@@ -1348,6 +1400,7 @@ public class LauncherModel extends BroadcastReceiver {
sBgFolders.clear();
sBgItemsIdMap.clear();
sBgDbIconCache.clear();
+ sBgWorkspaceScreens.clear();
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
@@ -1356,8 +1409,7 @@ public class LauncherModel extends BroadcastReceiver {
// +1 for the hotseat (it can be larger than the workspace)
// Load workspace in reverse order to ensure that latest items are loaded first (and
// before any earlier duplicates)
- final ItemInfo occupied[][][] =
- new ItemInfo[Launcher.SCREEN_COUNT + 1][mCellCountX + 1][mCellCountY + 1];
+ final HashMap<Long, ItemInfo[][]> occupied = new HashMap<Long, ItemInfo[][]>();
try {
final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
@@ -1439,7 +1491,7 @@ public class LauncherModel extends BroadcastReceiver {
info.id = c.getLong(idIndex);
container = c.getInt(containerIndex);
info.container = container;
- info.screen = c.getInt(screenIndex);
+ info.screenId = c.getInt(screenIndex);
info.cellX = c.getInt(cellXIndex);
info.cellY = c.getInt(cellYIndex);
// check & update map of what's occupied
@@ -1461,7 +1513,7 @@ public class LauncherModel extends BroadcastReceiver {
}
if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
loadOldDb) {
- info.screen = permuteScreens(info.screen);
+ info.screenId = permuteScreens(info.screenId);
}
sBgItemsIdMap.put(info.id, info);
@@ -1488,7 +1540,7 @@ public class LauncherModel extends BroadcastReceiver {
folderInfo.id = id;
container = c.getInt(containerIndex);
folderInfo.container = container;
- folderInfo.screen = c.getInt(screenIndex);
+ folderInfo.screenId = c.getInt(screenIndex);
folderInfo.cellX = c.getInt(cellXIndex);
folderInfo.cellY = c.getInt(cellYIndex);
@@ -1504,7 +1556,7 @@ public class LauncherModel extends BroadcastReceiver {
}
if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
loadOldDb) {
- folderInfo.screen = permuteScreens(folderInfo.screen);
+ folderInfo.screenId = permuteScreens(folderInfo.screenId);
}
sBgItemsIdMap.put(folderInfo.id, folderInfo);
@@ -1530,7 +1582,7 @@ public class LauncherModel extends BroadcastReceiver {
appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
provider.provider);
appWidgetInfo.id = id;
- appWidgetInfo.screen = c.getInt(screenIndex);
+ appWidgetInfo.screenId = c.getInt(screenIndex);
appWidgetInfo.cellX = c.getInt(cellXIndex);
appWidgetInfo.cellY = c.getInt(cellYIndex);
appWidgetInfo.spanX = c.getInt(spanXIndex);
@@ -1548,7 +1600,8 @@ public class LauncherModel extends BroadcastReceiver {
}
if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
loadOldDb) {
- appWidgetInfo.screen = permuteScreens(appWidgetInfo.screen);
+ appWidgetInfo.screenId =
+ permuteScreens(appWidgetInfo.screenId);
}
appWidgetInfo.container = c.getInt(containerIndex);
@@ -1587,17 +1640,86 @@ public class LauncherModel extends BroadcastReceiver {
}
}
+ if (loadOldDb) {
+ long maxScreenId = 0;
+ // If we're importing we use the old screen order.
+ for (ItemInfo item: sBgItemsIdMap.values()) {
+ long screenId = item.screenId;
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+ !sBgWorkspaceScreens.contains(screenId)) {
+ sBgWorkspaceScreens.add(screenId);
+ if (screenId > maxScreenId) {
+ maxScreenId = screenId;
+ }
+ }
+ }
+ Collections.sort(sBgWorkspaceScreens);
+ mApp.getLauncherProvider().updateMaxScreenId(maxScreenId);
+ updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
+ } else {
+ Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
+ final Cursor sc = contentResolver.query(screensUri, null, null, null, null);
+ TreeMap<Integer, Long> orderedScreens = new TreeMap<Integer, Long>();
+
+ try {
+ final int idIndex = sc.getColumnIndexOrThrow(
+ LauncherSettings.WorkspaceScreens._ID);
+ final int rankIndex = sc.getColumnIndexOrThrow(
+ LauncherSettings.WorkspaceScreens.SCREEN_RANK);
+ while (sc.moveToNext()) {
+ try {
+ long screenId = sc.getLong(idIndex);
+ int rank = sc.getInt(rankIndex);
+
+ orderedScreens.put(rank, screenId);
+ } catch (Exception e) {
+ Log.w(TAG, "Desktop items loading interrupted:", e);
+ }
+ }
+ } finally {
+ sc.close();
+ }
+
+ Iterator<Integer> iter = orderedScreens.keySet().iterator();
+ while (iter.hasNext()) {
+ sBgWorkspaceScreens.add(orderedScreens.get(iter.next()));
+ }
+
+ // Remove any empty screens
+ ArrayList<Long> unusedScreens = new ArrayList<Long>();
+ unusedScreens.addAll(sBgWorkspaceScreens);
+
+ for (ItemInfo item: sBgItemsIdMap.values()) {
+ long screenId = item.screenId;
+
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+ unusedScreens.contains(screenId)) {
+ unusedScreens.remove(screenId);
+ }
+ }
+
+ // If there are any empty screens remove them, and update.
+ if (unusedScreens.size() != 0) {
+ sBgWorkspaceScreens.removeAll(unusedScreens);
+ updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
+ }
+ }
+
if (DEBUG_LOADERS) {
Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
Log.d(TAG, "workspace layout: ");
+ Iterator<Long> iter = occupied.keySet().iterator();
+ int nScreens = occupied.size();
for (int y = 0; y < mCellCountY; y++) {
String line = "";
- for (int s = 0; s < Launcher.SCREEN_COUNT; s++) {
+
+ for (int s = 0; s < nScreens; s++) {
+ long screenId = iter.next();
if (s > 0) {
line += " | ";
}
for (int x = 0; x < mCellCountX; x++) {
- line += ((occupied[s][x][y] != null) ? "#" : ".");
+ line += ((occupied.get(screenId)[x][y] != null) ? "#" : ".");
}
}
Log.d(TAG, "[ " + line + " ]");
@@ -1608,7 +1730,7 @@ public class LauncherModel extends BroadcastReceiver {
// We rearrange the screens from the old launcher
// 12345 -> 34512
- private int permuteScreens(int screen) {
+ private long permuteScreens(long screen) {
if (screen >= 2) {
return screen - 2;
} else {
@@ -1649,7 +1771,7 @@ public class LauncherModel extends BroadcastReceiver {
});
for (ItemInfo info : allWorkspaceItems) {
if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (info.screen == currentScreen) {
+ if (info.screenId == currentScreen) {
currentScreenItems.add(info);
itemsOnScreen.add(info.id);
} else {
@@ -1683,7 +1805,7 @@ public class LauncherModel extends BroadcastReceiver {
for (LauncherAppWidgetInfo widget : appWidgets) {
if (widget == null) continue;
if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- widget.screen == currentScreen) {
+ widget.screenId == currentScreen) {
currentScreenWidgets.add(widget);
} else {
otherScreenWidgets.add(widget);
@@ -1708,7 +1830,7 @@ public class LauncherModel extends BroadcastReceiver {
FolderInfo folder = folders.get(id);
if (info == null || folder == null) continue;
if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- info.screen == currentScreen) {
+ info.screenId == currentScreen) {
currentScreenFolders.put(id, folder);
} else {
otherScreenFolders.put(id, folder);
@@ -1727,15 +1849,30 @@ public class LauncherModel extends BroadcastReceiver {
int cellCountY = LauncherModel.getCellCountY();
int screenOffset = cellCountX * cellCountY;
int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1); // +1 hotseat
- long lr = (lhs.container * containerOffset + lhs.screen * screenOffset +
+ long lr = (lhs.container * containerOffset + lhs.screenId * screenOffset +
lhs.cellY * cellCountX + lhs.cellX);
- long rr = (rhs.container * containerOffset + rhs.screen * screenOffset +
+ long rr = (rhs.container * containerOffset + rhs.screenId * screenOffset +
rhs.cellY * cellCountX + rhs.cellX);
return (int) (lr - rr);
}
});
}
+ private void bindWorkspaceScreens(final Callbacks oldCallbacks,
+ final ArrayList<Long> orderedScreens) {
+
+ final Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ if (callbacks != null) {
+ callbacks.bindScreens(orderedScreens);
+ }
+ }
+ };
+ runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ }
+
private void bindWorkspaceItems(final Callbacks oldCallbacks,
final ArrayList<ItemInfo> workspaceItems,
final ArrayList<LauncherAppWidgetInfo> appWidgets,
@@ -1830,11 +1967,13 @@ public class LauncherModel extends BroadcastReceiver {
new ArrayList<LauncherAppWidgetInfo>();
HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();
HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();
+ ArrayList<Long> orderedScreenIds = new ArrayList<Long>();
synchronized (sBgLock) {
workspaceItems.addAll(sBgWorkspaceItems);
appWidgets.addAll(sBgAppWidgets);
folders.putAll(sBgFolders);
itemsIdMap.putAll(sBgItemsIdMap);
+ orderedScreenIds.addAll(sBgWorkspaceScreens);
}
ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();
@@ -1867,6 +2006,8 @@ public class LauncherModel extends BroadcastReceiver {
};
runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);
+ bindWorkspaceScreens(oldCallbacks, orderedScreenIds);
+
// Load items on the current page
bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,
currentFolders, null);
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index f971a3743..91e58e2af 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -66,12 +66,13 @@ public class LauncherProvider extends ContentProvider {
private static final String DATABASE_NAME = "launcher.db";
- private static final int DATABASE_VERSION = 12;
+ private static final int DATABASE_VERSION = 13;
static final String OLD_AUTHORITY = "com.android.launcher2.settings";
static final String AUTHORITY = "com.android.launcher3.settings";
static final String TABLE_FAVORITES = "favorites";
+ static final String TABLE_WORKSPACE_SCREENS = "workspaceScreens";
static final String PARAMETER_NOTIFY = "notify";
static final String DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED =
"DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED";
@@ -90,6 +91,7 @@ public class LauncherProvider extends ContentProvider {
Uri.parse("content://" + AUTHORITY + "/appWidgetReset");
private DatabaseHelper mOpenHelper;
+ private static boolean sLoadOldDb;
@Override
public boolean onCreate() {
@@ -202,8 +204,18 @@ public class LauncherProvider extends ContentProvider {
}
}
- public long generateNewId() {
- return mOpenHelper.generateNewId();
+ public long generateNewItemId() {
+ return mOpenHelper.generateNewItemId();
+ }
+
+ public long generateNewScreenId() {
+ return mOpenHelper.generateNewScreenId();
+ }
+
+ // This is only required one time while loading the workspace during the
+ // upgrade path, and should never be called from anywhere else.
+ public void updateMaxScreenId(long maxScreenId) {
+ mOpenHelper.updateMaxScreenId(maxScreenId);
}
/**
@@ -213,7 +225,9 @@ public class LauncherProvider extends ContentProvider {
String spKey = LauncherAppState.getSharedPreferencesKey();
SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
- boolean loadOldDb = false;
+ boolean loadOldDb = false || sLoadOldDb;
+
+ sLoadOldDb = false;
if (sp.getBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, false)) {
SharedPreferences.Editor editor = sp.edit();
@@ -263,7 +277,8 @@ public class LauncherProvider extends ContentProvider {
private final Context mContext;
private final AppWidgetHost mAppWidgetHost;
- private long mMaxId = -1;
+ private long mMaxItemId = -1;
+ private long mMaxScreenId = -1;
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -272,8 +287,11 @@ public class LauncherProvider extends ContentProvider {
// In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
// the DB here
- if (mMaxId == -1) {
- mMaxId = initializeMaxId(getWritableDatabase());
+ if (mMaxItemId == -1) {
+ mMaxItemId = initializeMaxItemId(getWritableDatabase());
+ }
+ if (mMaxScreenId == -1) {
+ mMaxScreenId = initializeMaxScreenId(getWritableDatabase());
}
}
@@ -292,7 +310,8 @@ public class LauncherProvider extends ContentProvider {
public void onCreate(SQLiteDatabase db) {
if (LOGD) Log.d(TAG, "creating new launcher database");
- mMaxId = 1;
+ mMaxItemId = 1;
+ mMaxScreenId = 0;
db.execSQL("CREATE TABLE favorites (" +
"_id INTEGER PRIMARY KEY," +
@@ -314,6 +333,7 @@ public class LauncherProvider extends ContentProvider {
"uri TEXT," +
"displayMode INTEGER" +
");");
+ addWorkspacesTable(db);
// Database was just created, so wipe any previous widgets
if (mAppWidgetHost != null) {
@@ -327,6 +347,13 @@ public class LauncherProvider extends ContentProvider {
}
}
+ private void addWorkspacesTable(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + TABLE_WORKSPACE_SCREENS + " (" +
+ LauncherSettings.WorkspaceScreens._ID + " INTEGER," +
+ LauncherSettings.WorkspaceScreens.SCREEN_RANK + " INTEGER" +
+ ");");
+ }
+
private void setFlagToLoadDefaultWorkspaceLater() {
String spKey = LauncherAppState.getSharedPreferencesKey();
SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
@@ -504,8 +531,8 @@ public class LauncherProvider extends ContentProvider {
if (version < 9) {
// The max id is not yet set at this point (onUpgrade is triggered in the ctor
// before it gets a change to get set, so we need to read it here when we use it)
- if (mMaxId == -1) {
- mMaxId = initializeMaxId(db);
+ if (mMaxItemId == -1) {
+ mMaxItemId = initializeMaxItemId(db);
}
// Add default hotseat icons
@@ -524,9 +551,24 @@ public class LauncherProvider extends ContentProvider {
version = 12;
}
+ if (version < 13) {
+ // With the new shrink-wrapped and re-orderable workspaces, it makes sense
+ // to persist workspace screens and their relative order.
+ mMaxScreenId = 0;
+
+ // This will never happen in the wild, but when we switch to using workspace
+ // screen ids, redo the import from old launcher.
+ sLoadOldDb = true;
+
+ addWorkspacesTable(db);
+ version = 13;
+ }
+
if (version != DATABASE_VERSION) {
Log.w(TAG, "Destroying all old data.");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_WORKSPACE_SCREENS);
+
onCreate(db);
}
}
@@ -672,15 +714,15 @@ public class LauncherProvider extends ContentProvider {
// constructor from the worker thread; however, this doesn't extend until after the
// constructor is called, and we only pass a reference to LauncherProvider to LauncherApp
// after that point
- public long generateNewId() {
- if (mMaxId < 0) {
- throw new RuntimeException("Error: max id was not initialized");
+ public long generateNewItemId() {
+ if (mMaxItemId < 0) {
+ throw new RuntimeException("Error: max item id was not initialized");
}
- mMaxId += 1;
- return mMaxId;
+ mMaxItemId += 1;
+ return mMaxItemId;
}
- private long initializeMaxId(SQLiteDatabase db) {
+ private long initializeMaxItemId(SQLiteDatabase db) {
Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null);
// get the result
@@ -694,7 +736,44 @@ public class LauncherProvider extends ContentProvider {
}
if (id == -1) {
- throw new RuntimeException("Error: could not query max id");
+ throw new RuntimeException("Error: could not query max item id");
+ }
+
+ return id;
+ }
+
+ // Generates a new ID to use for an workspace screen in your database. This method
+ // should be only called from the main UI thread. As an exception, we do call it when we
+ // call the constructor from the worker thread; however, this doesn't extend until after the
+ // constructor is called, and we only pass a reference to LauncherProvider to LauncherApp
+ // after that point
+ public long generateNewScreenId() {
+ if (mMaxScreenId < 0) {
+ throw new RuntimeException("Error: max screen id was not initialized");
+ }
+ mMaxScreenId += 1;
+ return mMaxScreenId;
+ }
+
+ public void updateMaxScreenId(long maxScreenId) {
+ mMaxScreenId = maxScreenId;
+ }
+
+ private long initializeMaxScreenId(SQLiteDatabase db) {
+ Cursor c = db.rawQuery("SELECT MAX(" + LauncherSettings.WorkspaceScreens._ID + ") FROM " + TABLE_WORKSPACE_SCREENS, null);
+
+ // get the result
+ final int maxIdIndex = 0;
+ long id = -1;
+ if (c != null && c.moveToNext()) {
+ id = c.getLong(maxIdIndex);
+ }
+ if (c != null) {
+ c.close();
+ }
+
+ if (id == -1) {
+ throw new RuntimeException("Error: could not query max screen id");
}
return id;
@@ -959,7 +1038,7 @@ public class LauncherProvider extends ContentProvider {
cn = new ComponentName(packages[0], className);
info = packageManager.getActivityInfo(cn, 0);
}
- id = generateNewId();
+ id = generateNewItemId();
intent.setComponent(cn);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
@@ -968,7 +1047,7 @@ public class LauncherProvider extends ContentProvider {
values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION);
values.put(Favorites.SPANX, 1);
values.put(Favorites.SPANY, 1);
- values.put(Favorites._ID, generateNewId());
+ values.put(Favorites._ID, generateNewItemId());
if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
return -1;
}
@@ -983,7 +1062,7 @@ public class LauncherProvider extends ContentProvider {
values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_FOLDER);
values.put(Favorites.SPANX, 1);
values.put(Favorites.SPANY, 1);
- long id = generateNewId();
+ long id = generateNewItemId();
values.put(Favorites._ID, id);
if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) <= 0) {
return -1;
@@ -1088,7 +1167,6 @@ public class LauncherProvider extends ContentProvider {
return false;
}
-
private boolean addAppWidget(SQLiteDatabase db, ContentValues values, ComponentName cn,
int spanX, int spanY, Bundle extras) {
boolean allocatedAppWidgets = false;
@@ -1101,7 +1179,7 @@ public class LauncherProvider extends ContentProvider {
values.put(Favorites.SPANX, spanX);
values.put(Favorites.SPANY, spanY);
values.put(Favorites.APPWIDGET_ID, appWidgetId);
- values.put(Favorites._ID, generateNewId());
+ values.put(Favorites._ID, generateNewItemId());
dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
allocatedAppWidgets = true;
@@ -1146,7 +1224,7 @@ public class LauncherProvider extends ContentProvider {
return -1;
}
- long id = generateNewId();
+ long id = generateNewItemId();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
values.put(Favorites.INTENT, intent.toUri(0));
values.put(Favorites.TITLE, r.getString(titleResId));
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index eb395c8bf..a2b9c8143 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -91,6 +91,26 @@ class LauncherSettings {
}
/**
+ * Workspace Screens.
+ *
+ * Tracks the order of workspace screens.
+ */
+ static final class WorkspaceScreens implements BaseColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ static final Uri CONTENT_URI = Uri.parse("content://" +
+ LauncherProvider.AUTHORITY + "/" + LauncherProvider.TABLE_WORKSPACE_SCREENS +
+ "?" + LauncherProvider.PARAMETER_NOTIFY + "=true");
+
+ /**
+ * The rank of this screen -- ie. how it is ordered relative to the other screens.
+ * <P>Type: INTEGER</P>
+ */
+ static final String SCREEN_RANK = "screenRank";
+ }
+
+ /**
* Favorites.
*/
static final class Favorites implements BaseLauncherColumns {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index abf8bbd14..842dc2034 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -491,7 +491,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (!mIsDataReady) {
+ if (!mIsDataReady || getChildCount() == 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
@@ -650,7 +650,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (!mIsDataReady) {
+ if (!mIsDataReady || getChildCount() == 0) {
return;
}
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index 5249fec02..224b2fca4 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -145,7 +145,7 @@ class ShortcutInfo extends ItemInfo {
@Override
public String toString() {
return "ShortcutInfo(title=" + title.toString() + "intent=" + intent + "id=" + this.id
- + " type=" + this.itemType + " container=" + this.container + " screen=" + screen
+ + " type=" + this.itemType + " container=" + this.container + " screen=" + screenId
+ " cellX=" + cellX + " cellY=" + cellY + " spanX=" + spanX + " spanY=" + spanY
+ " dropPos=" + dropPos + ")";
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 9a75cc1d5..853e9ee85 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -60,6 +60,7 @@ import com.android.launcher3.LauncherSettings.Favorites;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -105,9 +106,15 @@ public class Workspace extends SmoothPagedView
private IBinder mWindowToken;
private static final float WALLPAPER_SCREENS_SPAN = 2f;
- public int mNumPagesToLeft = 0;
private int mDefaultPage;
+ // The screen id used for the empty screen always present to the right.
+ private final static long EXTRA_EMPTY_SCREEN_ID = -201;
+ private final static long CUSTOM_CONTENT_SCREEN_ID = -301;
+
+ private HashMap<Long, CellLayout> mWorkspaceScreens = new HashMap<Long, CellLayout>();
+ private ArrayList<Long> mScreenOrder = new ArrayList<Long>();
+
/**
* CellInfo for the cell that is currently being dragged
*/
@@ -254,6 +261,7 @@ public class Workspace extends SmoothPagedView
private float[] mNewBackgroundAlphas;
private float[] mNewAlphas;
private float[] mNewRotationYs;
+ private int mLastChildCount = -1;
private float mTransitionProgress;
private final Runnable mBindPages = new Runnable() {
@@ -375,6 +383,7 @@ public class Workspace extends SmoothPagedView
return size;
}
}
+
public Rect estimateItemPosition(CellLayout cl, ItemInfo pendingInfo,
int hCell, int vCell, int hSpan, int vSpan) {
Rect r = new Rect();
@@ -402,13 +411,6 @@ public class Workspace extends SmoothPagedView
UninstallShortcutReceiver.disableAndFlushUninstallQueue(getContext());
}
- // Just a hack so that if a custom content screen is added to the left, we adjust the
- // default screen accordingly so that it stays the same.
- void incrementNumScreensToLeft() {
- mDefaultPage++;
- mNumPagesToLeft++;
- }
-
/**
* Initializes various states for this workspace.
*/
@@ -489,19 +491,131 @@ public class Workspace extends SmoothPagedView
return mTouchState != TOUCH_STATE_REST;
}
- /**
- * Adds the specified child in the specified screen. The position and dimension of
- * the child are defined by x, y, spanX and spanY.
- *
- * @param child The child to add in one of the workspace's screens.
- * @param screen The screen in which to add the child.
- * @param x The X position of the child in the screen's grid.
- * @param y The Y position of the child in the screen's grid.
- * @param spanX The number of cells spanned horizontally by the child.
- * @param spanY The number of cells spanned vertically by the child.
- */
- void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY) {
- addInScreen(child, container, screen, x, y, spanX, spanY, false);
+ public long insertNewWorkspaceScreen(long screenId) {
+ return insertNewWorkspaceScreen(screenId, true);
+ }
+
+ public long insertNewWorkspaceScreenOnBind(long screenId) {
+ return insertNewWorkspaceScreen(screenId, false);
+ }
+
+ // If screen id is -1, this indicates there is no screen assigned, so we generate
+ // a new screen id.
+ public long insertNewWorkspaceScreen(long screenId, boolean updateDb) {
+ CellLayout newScreen = (CellLayout)
+ mLauncher.getLayoutInflater().inflate(R.layout.workspace_screen, null);
+
+ addView(newScreen, getChildCount());
+ mWorkspaceScreens.put(screenId, newScreen);
+ mScreenOrder.add(screenId);
+ if (updateDb) {
+ // On bind we don't need to update the screens in the database.
+ LauncherModel.updateWorkspaceScreenOrder(mLauncher, mScreenOrder);
+ }
+ return screenId;
+ }
+
+ public void addCustomContentToLeft(View customContent) {
+ CellLayout customScreen = (CellLayout)
+ mLauncher.getLayoutInflater().inflate(R.layout.workspace_custom_content, null);
+
+ int spanX = customScreen.getCountX();
+ int spanY = customScreen.getCountY();
+
+ CellLayout.LayoutParams lp = new CellLayout.LayoutParams(0, 0, spanX, spanY);
+ lp.canReorder = false;
+
+ customScreen.addViewToCellLayout(customContent, 0, 0, lp, true);
+
+ addView(customScreen, 0);
+
+ mWorkspaceScreens.put(CUSTOM_CONTENT_SCREEN_ID, customScreen);
+ mScreenOrder.add(0, CUSTOM_CONTENT_SCREEN_ID);
+
+ // Ensure that the current page and default page are maintained.
+ mDefaultPage++;
+ setCurrentPage(getCurrentPage() + 1);
+ }
+
+ public long commitExtraEmptyScreen() {
+ CellLayout cl = mWorkspaceScreens.get(EXTRA_EMPTY_SCREEN_ID);
+ mScreenOrder.remove(EXTRA_EMPTY_SCREEN_ID);
+
+ long newId = LauncherAppState.getInstance().getLauncherProvider().generateNewScreenId();
+ mWorkspaceScreens.put(newId, cl);
+ mScreenOrder.add(newId);
+
+ addExtraEmptyScreen();
+ return newId;
+ }
+
+ public void addExtraEmptyScreen() {
+ insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_ID, false);
+ }
+
+ public CellLayout getScreenWithId(long screenId) {
+ CellLayout layout = mWorkspaceScreens.get(screenId);
+ return layout;
+ }
+
+ public long getIdForScreen(CellLayout layout) {
+ Iterator<Long> iter = mWorkspaceScreens.keySet().iterator();
+ while (iter.hasNext()) {
+ long id = iter.next();
+ if (mWorkspaceScreens.get(id) == layout) {
+ return id;
+ }
+ }
+ return -1;
+ }
+
+ public int getPageIndexForScreenId(long screenId) {
+ return indexOfChild(mWorkspaceScreens.get(screenId));
+ }
+
+ public long getScreenIdForPageIndex(int index) {
+ return mScreenOrder.get(index);
+ }
+
+ public void stripEmptyScreens() {
+ ArrayList<Long> removeScreens = new ArrayList<Long>();
+ for (Long id: mWorkspaceScreens.keySet()) {
+ CellLayout cl = mWorkspaceScreens.get(id);
+ if (id != EXTRA_EMPTY_SCREEN_ID && cl.getShortcutsAndWidgets().getChildCount() == 0) {
+ removeScreens.add(id);
+ }
+ }
+
+ int pageShift = 0;
+ for (Long id: removeScreens) {
+ CellLayout cl = mWorkspaceScreens.get(id);
+ mWorkspaceScreens.remove(id);
+ mScreenOrder.remove(id);
+ if (indexOfChild(cl) < mCurrentPage) {
+ pageShift++;
+ }
+ removeView(cl);
+ }
+ setCurrentPage(mCurrentPage - pageShift);
+ }
+
+ // See implementation for parameter definition.
+ void addInScreen(View child, long container, long screenId,
+ int x, int y, int spanX, int spanY) {
+ addInScreen(child, container, screenId, x, y, spanX, spanY, false, false);
+ }
+
+ // At bind time, we use the rank (screenId) to compute x and y for hotseat items.
+ // See implementation for parameter definition.
+ void addInScreenFromBind(View child, long container, long screenId, int x, int y,
+ int spanX, int spanY) {
+ addInScreen(child, container, screenId, x, y, spanX, spanY, false, true);
+ }
+
+ // See implementation for parameter definition.
+ void addInScreen(View child, long container, long screenId, int x, int y, int spanX, int spanY,
+ boolean insert) {
+ addInScreen(child, container, screenId, x, y, spanX, spanY, insert, false);
}
/**
@@ -509,23 +623,30 @@ public class Workspace extends SmoothPagedView
* the child are defined by x, y, spanX and spanY.
*
* @param child The child to add in one of the workspace's screens.
- * @param screen The screen in which to add the child.
+ * @param screenId The screen in which to add the child.
* @param x The X position of the child in the screen's grid.
* @param y The Y position of the child in the screen's grid.
* @param spanX The number of cells spanned horizontally by the child.
* @param spanY The number of cells spanned vertically by the child.
* @param insert When true, the child is inserted at the beginning of the children list.
+ * @param computeXYFromRank When true, we use the rank (stored in screenId) to compute
+ * the x and y position in which to place hotseat items. Otherwise
+ * we use the x and y position to compute the rank.
*/
- void addInScreen(View child, long container, int screen, int x, int y, int spanX, int spanY,
- boolean insert) {
+ void addInScreen(View child, long container, long screenId, int x, int y, int spanX, int spanY,
+ boolean insert, boolean computeXYFromRank) {
if (container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- if (screen < 0 || screen >= getChildCount()) {
- Log.e(TAG, "The screen must be >= 0 and < " + getChildCount()
- + " (was " + screen + "); skipping child");
+ if (getScreenWithId(screenId) == null) {
+ Log.e(TAG, "Skipping child, screenId " + screenId + " not found");
return;
}
}
+ // If an item is added to the extra empty screen, we convert it to a real
+ if (screenId == EXTRA_EMPTY_SCREEN_ID) {
+ screenId = commitExtraEmptyScreen();
+ }
+
final CellLayout layout;
if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
layout = mLauncher.getHotseat().getLayout();
@@ -536,21 +657,18 @@ public class Workspace extends SmoothPagedView
((FolderIcon) child).setTextVisible(false);
}
- if (screen < 0) {
- screen = mLauncher.getHotseat().getOrderInHotseat(x, y);
+ if (computeXYFromRank) {
+ x = mLauncher.getHotseat().getCellXFromOrder((int) screenId);
+ y = mLauncher.getHotseat().getCellYFromOrder((int) screenId);
} else {
- // Note: We do this to ensure that the hotseat is always laid out in the orientation
- // of the hotseat in order regardless of which orientation they were added
- x = mLauncher.getHotseat().getCellXFromOrder(screen);
- y = mLauncher.getHotseat().getCellYFromOrder(screen);
+ screenId = mLauncher.getHotseat().getOrderInHotseat(x, y);
}
} else {
// Show folder title if not in the hotseat
if (child instanceof FolderIcon) {
((FolderIcon) child).setTextVisible(true);
}
-
- layout = (CellLayout) getChildAt(screen);
+ layout = getScreenWithId(screenId);
child.setOnKeyListener(new IconKeyEventListener());
}
@@ -571,7 +689,7 @@ public class Workspace extends SmoothPagedView
}
// Get the canonical child id to uniquely represent this view in this screen
- int childId = LauncherModel.getCellLayoutChildId(container, screen, x, y, spanX, spanY);
+ int childId = LauncherModel.getCellLayoutChildId(container, screenId, x, y, spanX, spanY);
boolean markCellsAsOccupied = !(child instanceof Folder);
if (!layout.addViewToCellLayout(child, insert ? 0 : -1, childId, lp, markCellsAsOccupied)) {
// TODO: This branch occurs when the workspace is adding views
@@ -912,7 +1030,8 @@ public class Workspace extends SmoothPagedView
private void syncWallpaperOffsetWithScroll() {
final boolean enableWallpaperEffects = isHardwareAccelerated();
if (enableWallpaperEffects) {
- mWallpaperOffset.setFinalX(wallpaperOffsetForCurrentScroll());
+ // TODO: figure out what to do about parallax, for now disable it
+ //mWallpaperOffset.setFinalX(wallpaperOffsetForCurrentScroll());
}
}
@@ -968,6 +1087,10 @@ public class Workspace extends SmoothPagedView
snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION);
}
+ protected void snapToScreenId(long screenId, Runnable r) {
+ snapToPage(getPageIndexForScreenId(screenId), r);
+ }
+
private void computeWallpaperScrollRatio(int page) {
// Here, we determine what the desired scroll would be with and without a layout scale,
// and compute a ratio between the two. This allows us to adjust the wallpaper offset
@@ -1558,7 +1681,7 @@ public class Workspace extends SmoothPagedView
private void initAnimationArrays() {
final int childCount = getChildCount();
- if (mOldTranslationXs != null) return;
+ if (mLastChildCount == childCount) return;
mOldTranslationXs = new float[childCount];
mOldTranslationYs = new float[childCount];
mOldScaleXs = new float[childCount];
@@ -1958,16 +2081,15 @@ public class Workspace extends SmoothPagedView
showScrollingIndicator(false);
}
- void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, int screen,
+ void addApplicationShortcut(ShortcutInfo info, CellLayout target, long container, long screenId,
int cellX, int cellY, boolean insertAtFirst, int intersectX, int intersectY) {
View view = mLauncher.createShortcut(R.layout.application, target, (ShortcutInfo) info);
final int[] cellXY = new int[2];
target.findCellForSpanThatIntersects(cellXY, 1, 1, intersectX, intersectY);
- addInScreen(view, container, screen, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
+ addInScreen(view, container, screenId, cellXY[0], cellXY[1], 1, 1, insertAtFirst);
- int adjustedScreen = screen - mNumPagesToLeft;
- LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, adjustedScreen, cellXY[0],
+ LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screenId, cellXY[0],
cellXY[1]);
}
@@ -2122,7 +2244,7 @@ public class Workspace extends SmoothPagedView
if (v == null || hasntMoved || !mCreateUserFolderOnDrop) return false;
mCreateUserFolderOnDrop = false;
- final int screen = (targetCell == null) ? mDragInfo.screen : indexOfChild(target);
+ final long screenId = (targetCell == null) ? mDragInfo.screenId : getIdForScreen(target);
boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);
@@ -2140,7 +2262,7 @@ public class Workspace extends SmoothPagedView
target.removeView(v);
FolderIcon fi =
- mLauncher.addFolder(target, container, screen, targetCell[0], targetCell[1]);
+ mLauncher.addFolder(target, container, screenId, targetCell[0], targetCell[1]);
destInfo.cellX = -1;
destInfo.cellY = -1;
sourceInfo.cellX = -1;
@@ -2215,8 +2337,8 @@ public class Workspace extends SmoothPagedView
long container = hasMovedIntoHotseat ?
LauncherSettings.Favorites.CONTAINER_HOTSEAT :
LauncherSettings.Favorites.CONTAINER_DESKTOP;
- int screen = (mTargetCell[0] < 0) ?
- mDragInfo.screen : indexOfChild(dropTargetLayout);
+ long screenId = (mTargetCell[0] < 0) ?
+ mDragInfo.screenId : getIdForScreen(dropTargetLayout);
int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
// First we find the cell nearest to point at which the item is
@@ -2267,9 +2389,9 @@ public class Workspace extends SmoothPagedView
resultSpan[1]);
}
- if (mCurrentPage != screen && !hasMovedIntoHotseat) {
- snapScreen = screen;
- snapToPage(screen);
+ if (getScreenIdForPageIndex(mCurrentPage) != screenId && !hasMovedIntoHotseat) {
+ snapScreen = getPageIndexForScreenId(screenId);
+ snapToPage(snapScreen);
}
if (foundCell) {
@@ -2277,7 +2399,7 @@ public class Workspace extends SmoothPagedView
if (hasMovedLayouts) {
// Reparent the view
getParentCellLayoutForView(cell).removeView(cell);
- addInScreen(cell, container, screen, mTargetCell[0], mTargetCell[1],
+ addInScreen(cell, container, screenId, mTargetCell[0], mTargetCell[1],
info.spanX, info.spanY);
}
@@ -2288,7 +2410,7 @@ public class Workspace extends SmoothPagedView
lp.cellHSpan = item.spanX;
lp.cellVSpan = item.spanY;
lp.isLockedToGrid = true;
- cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screen,
+ cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screenId,
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
@@ -2319,10 +2441,7 @@ public class Workspace extends SmoothPagedView
}
}
- //TODO: This is a hack on top of a hack, but items aren't being saved
- // to the correct screen due to the extra screen.
- int adjustedScreen = screen - mNumPagesToLeft;
- LauncherModel.moveItemInDatabase(mLauncher, info, container, adjustedScreen, lp.cellX,
+ LauncherModel.moveItemInDatabase(mLauncher, info, container, screenId, lp.cellX,
lp.cellY);
} else {
// If we can't find a drop location, we return the item to its original position
@@ -2369,22 +2488,22 @@ public class Workspace extends SmoothPagedView
}
}
- public void setFinalScrollForPageChange(int screen) {
- if (screen >= 0) {
+ public void setFinalScrollForPageChange(int pageIndex) {
+ CellLayout cl = (CellLayout) getChildAt(pageIndex);
+ if (cl != null) {
mSavedScrollX = getScrollX();
- CellLayout cl = (CellLayout) getChildAt(screen);
mSavedTranslationX = cl.getTranslationX();
mSavedRotationY = cl.getRotationY();
- final int newX = getChildOffset(screen) - getRelativeChildOffset(screen);
+ final int newX = getChildOffset(pageIndex) - getRelativeChildOffset(pageIndex);
setScrollX(newX);
cl.setTranslationX(0f);
cl.setRotationY(0f);
}
}
- public void resetFinalScrollForPageChange(int screen) {
- if (screen >= 0) {
- CellLayout cl = (CellLayout) getChildAt(screen);
+ public void resetFinalScrollForPageChange(int pageIndex) {
+ if (pageIndex >= 0) {
+ CellLayout cl = (CellLayout) getChildAt(pageIndex);
setScrollX(mSavedScrollX);
cl.setTranslationX(mSavedTranslationX);
cl.setRotationY(mSavedRotationY);
@@ -3047,10 +3166,11 @@ public class Workspace extends SmoothPagedView
final long container = mLauncher.isHotseatLayout(cellLayout) ?
LauncherSettings.Favorites.CONTAINER_HOTSEAT :
LauncherSettings.Favorites.CONTAINER_DESKTOP;
- final int screen = indexOfChild(cellLayout);
- if (!mLauncher.isHotseatLayout(cellLayout) && screen != mCurrentPage
+ final long screenId = getIdForScreen(cellLayout);
+ if (!mLauncher.isHotseatLayout(cellLayout)
+ && screenId != getScreenIdForPageIndex(mCurrentPage)
&& mState != State.SPRING_LOADED) {
- snapToPage(screen);
+ snapToScreenId(screenId, null);
}
if (info instanceof PendingAddItemInfo) {
@@ -3101,11 +3221,11 @@ public class Workspace extends SmoothPagedView
span[0] = item.spanX;
span[1] = item.spanY;
mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
- container, screen, mTargetCell, span, null);
+ container, screenId, mTargetCell, span, null);
break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
mLauncher.processShortcutFromDrop(pendingInfo.componentName,
- container, screen, mTargetCell, null);
+ container, screenId, mTargetCell, null);
break;
default:
throw new IllegalStateException("Unknown item type: " +
@@ -3177,14 +3297,13 @@ public class Workspace extends SmoothPagedView
} else {
cellLayout.findCellForSpan(mTargetCell, 1, 1);
}
- addInScreen(view, container, screen, mTargetCell[0], mTargetCell[1], info.spanX,
+ addInScreen(view, container, screenId, mTargetCell[0], mTargetCell[1], info.spanX,
info.spanY, insertAtFirst);
cellLayout.onDropChild(view);
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
cellLayout.getShortcutsAndWidgets().measureChild(view);
- int adjustedScreen = screen - mNumPagesToLeft;
- LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, adjustedScreen,
+ LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screenId,
lp.cellX, lp.cellY);
if (d.dragView != null) {
@@ -3400,7 +3519,7 @@ public class Workspace extends SmoothPagedView
if (mLauncher.isHotseatLayout(target)) {
cellLayout = mLauncher.getHotseat().getLayout();
} else {
- cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
+ cellLayout = getScreenWithId(mDragInfo.screenId);
}
cellLayout.onDropChild(mDragInfo.cell);
}
@@ -3410,6 +3529,8 @@ public class Workspace extends SmoothPagedView
mDragOutline = null;
mDragInfo = null;
+ stripEmptyScreens();
+
// Hide the scrolling indicator after you pick up an item
hideScrollingIndicator(false);
}
@@ -3417,11 +3538,11 @@ public class Workspace extends SmoothPagedView
void updateItemLocationsInDatabase(CellLayout cl) {
int count = cl.getShortcutsAndWidgets().getChildCount();
- int screen = indexOfChild(cl);
+ long screenId = getIdForScreen(cl);
int container = Favorites.CONTAINER_DESKTOP;
if (mLauncher.isHotseatLayout(cl)) {
- screen = -1;
+ screenId = -1;
container = Favorites.CONTAINER_HOTSEAT;
}
@@ -3431,8 +3552,7 @@ public class Workspace extends SmoothPagedView
// Null check required as the AllApps button doesn't have an item info
if (info != null && info.requiresDbUpdate) {
info.requiresDbUpdate = false;
- int adjustedScreen = screen - mNumPagesToLeft;
- LauncherModel.modifyItemInDatabase(mLauncher, info, container, adjustedScreen, info.cellX,
+ LauncherModel.modifyItemInDatabase(mLauncher, info, container, screenId, info.cellX,
info.cellY, info.spanX, info.spanY);
}
}
@@ -3512,11 +3632,11 @@ public class Workspace extends SmoothPagedView
void saveWorkspaceScreenToDb(CellLayout cl) {
int count = cl.getShortcutsAndWidgets().getChildCount();
- int screen = indexOfChild(cl);
+ long screenId = getIdForScreen(cl);
int container = Favorites.CONTAINER_DESKTOP;
if (mLauncher.isHotseatLayout(cl)) {
- screen = -1;
+ screenId = -1;
container = Favorites.CONTAINER_HOTSEAT;
}
@@ -3525,7 +3645,7 @@ public class Workspace extends SmoothPagedView
ItemInfo info = (ItemInfo) v.getTag();
// Null check required as the AllApps button doesn't have an item info
if (info != null) {
- LauncherModel.addItemToDatabase(mLauncher, info, container, screen, info.cellX,
+ LauncherModel.addItemToDatabase(mLauncher, info, container, screenId, info.cellX,
info.cellY, false);
}
if (v instanceof FolderIcon) {