diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java index 21254ab292..7959d40d4c 100644 --- a/src/com/android/launcher3/FolderInfo.java +++ b/src/com/android/launcher3/FolderInfo.java @@ -45,6 +45,12 @@ public class FolderInfo extends ItemInfo { */ public static final int FLAG_MULTI_PAGE_ANIMATION = 0x00000004; + /** + * The folder items ranks have been updated such that they appear unchanged with the new + * permutation display logic. + */ + public static final int FLAG_ITEM_RANKS_UPDATED = 0x00000008; + public int options; /** diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 4813571f54..a4cd1913ed 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -56,6 +56,7 @@ import com.android.launcher3.LauncherSettings.WorkspaceScreens; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dynamicui.ExtractionUtils; +import com.android.launcher3.folder.FolderPagedView; import com.android.launcher3.graphics.IconShapeOverride; import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.DbDowngradeHelper; @@ -725,6 +726,87 @@ public class LauncherProvider extends ContentProvider { + "';l.profile=" + serial + ";', ';') where itemType = 0;"; db.execSQL(sql); } + + updateExistingFoldersToMatchPrePermutationLayout(db); + } + + /** + * We have changed the way we display items in Folders, but we want existing folders to + * appear the same. + * + * To make this change invisible to existing Folders, we need to update the ranks of the + * items such that, when displayed using the permutation, the order remains the same. + */ + private void updateExistingFoldersToMatchPrePermutationLayout(SQLiteDatabase db) { + InvariantDeviceProfile idp = new InvariantDeviceProfile(mContext); + int maxCols = idp.numFolderColumns; + int maxRows = idp.numFolderRows; + + try (SQLiteTransaction t = new SQLiteTransaction(db)) { + Cursor c = db.query(Favorites.TABLE_NAME, + new String[] {Favorites._ID, Favorites.OPTIONS}, + "itemType=" + Favorites.ITEM_TYPE_FOLDER, null, null, null, null); + + // For every Folder + while (c.moveToNext()) { + final long folderId = c.getLong(c.getColumnIndexOrThrow(Favorites._ID)); + int options = c.getInt(c.getColumnIndexOrThrow(Favorites.OPTIONS)); + + if ((options & FolderInfo.FLAG_ITEM_RANKS_UPDATED) != 0) { + // The folder has already been updated. + continue; + } + + // For each item in the Folder + Cursor c2 = db.query(Favorites.TABLE_NAME, new String[] { + Favorites._ID, Favorites.RANK, Favorites.CELLX, Favorites.CELLY, + Favorites.OPTIONS}, + "container=" + folderId, null, null, null, null); + + int numItemsInFolder = c2.getCount(); + + // Calculate the grid size. + int[] gridXY = new int[2]; + FolderPagedView.calculateGridSize(numItemsInFolder, 0, 0, maxCols, maxRows, + maxCols * maxRows, gridXY); + int gridX = gridXY[0]; + int gridY = gridXY[1]; + int maxItemsPerPage = gridX * gridY; + + // We create a mapping from the permutation to the original rank (ie. the + // inverse permutation). This is what we'll use to set the folder items so that + // they appear in their original order. + int[] inversion = new int[numItemsInFolder]; + for (int i = 0; i < numItemsInFolder; ++i) { + int permutation = FolderPagedView.getReadingOrderPosForRank(i, + maxItemsPerPage, gridX, null); + inversion[permutation] = i; + } + + // Now we update the ranks of the folder items. Note that cellX/cellY stay the + // same, due to the permutation. + for (int i = 0; i < numItemsInFolder && c2.moveToNext(); ++i) { + final int rank = c2.getInt(c2.getColumnIndexOrThrow(Favorites.RANK)); + + SQLiteStatement updateItem = db.compileStatement( + "UPDATE favorites SET rank=" + inversion[rank] + " WHERE _id=?"); + updateItem.bindLong(1, c2.getInt(c2.getColumnIndexOrThrow(Favorites._ID))); + updateItem.executeUpdateDelete(); + } + c2.close(); + + // Mark the folder as having been updated. + options |= FolderInfo.FLAG_ITEM_RANKS_UPDATED; + SQLiteStatement updateFolder = db.compileStatement( + "UPDATE favorites SET options=" + options + " WHERE _id=?"); + updateFolder.bindLong(1, folderId); + updateFolder.executeUpdateDelete(); + } + c.close(); + t.commit(); + } catch (SQLException ex) { + Log.w(TAG, "Error updating folder items to match permutation.", ex); + } } @Override diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java index 21631fa24c..bc26fbef8c 100644 --- a/src/com/android/launcher3/folder/FolderPagedView.java +++ b/src/com/android/launcher3/folder/FolderPagedView.java @@ -755,6 +755,10 @@ public class FolderPagedView extends PagedView { return mMaxItemsPerPage; } + public int getReadingOrderPosForRank(int rank) { + return getReadingOrderPosForRank(rank, mMaxItemsPerPage, mGridCountX, sTmpArray); + } + /** * Returns the reading order position for a given rank. * @@ -763,34 +767,44 @@ public class FolderPagedView extends PagedView { * * R0 R1 R4 * R2 R3 R5 + * + * @param outXY If notnull, we also return the cell X/Y position. */ - public int getReadingOrderPosForRank(int rank) { - if (rank >= mMaxItemsPerPage) { + public static int getReadingOrderPosForRank(int rank, int maxItemsPerPage, int gridX, + int[] outXY) { + outXY = outXY == null ? sTmpArray : outXY; + getCellXYPositionForRank(rank, maxItemsPerPage, gridX, outXY); + + if (rank >= maxItemsPerPage) { return rank; } - getCellXYPositionForRank(rank, sTmpArray); - return sTmpArray[0] + (mGridCountX * sTmpArray[1]); + return outXY[0] + (gridX * outXY[1]); + } + + public void getCellXYPositionForRank(int rank, int[] outXY) { + getCellXYPositionForRank(rank, mMaxItemsPerPage, mGridCountX, outXY); } /** * Returns the cell XY position for a Folder item with the given rank. */ - public void getCellXYPositionForRank(int rank, int[] outXY) { - boolean onFirstPage = rank < mMaxItemsPerPage; + public static void getCellXYPositionForRank(int rank, int maxItemsPerPage, int gridX, + int[] outXY) { + boolean onFirstPage = rank < maxItemsPerPage; - if (onFirstPage && mGridCountX == 3) { + if (onFirstPage && gridX == 3) { outXY[0] = FolderPermutation.THREE_COLS[rank][0]; outXY[1] = FolderPermutation.THREE_COLS[rank][1]; - } else if (onFirstPage && mGridCountX == 4) { + } else if (onFirstPage && gridX == 4) { outXY[0] = FolderPermutation.FOUR_COLS[rank][0]; outXY[1] = FolderPermutation.FOUR_COLS[rank][1]; - } else if (onFirstPage && mGridCountX == 5) { + } else if (onFirstPage && gridX == 5) { outXY[0] = FolderPermutation.FIVE_COLS[rank][0]; outXY[1] = FolderPermutation.FIVE_COLS[rank][1]; } else { - outXY[0] = (rank % mMaxItemsPerPage) % mGridCountX; - outXY[1] = (rank % mMaxItemsPerPage) / mGridCountX; + outXY[0] = (rank % maxItemsPerPage) % gridX; + outXY[1] = (rank % maxItemsPerPage) / gridX; } }