summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/launcher3/DragLayer.java73
-rw-r--r--src/com/android/launcher3/Launcher.java3
-rw-r--r--src/com/android/launcher3/LauncherModel.java126
-rw-r--r--src/com/android/launcher3/LauncherProvider.java155
-rw-r--r--src/com/android/launcher3/PagedView.java4
-rw-r--r--src/com/android/launcher3/Utilities.java95
-rw-r--r--src/com/android/launcher3/Workspace.java8
7 files changed, 299 insertions, 165 deletions
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index 3c064badb..514dca29f 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -327,84 +327,15 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
*/
public float getDescendantCoordRelativeToSelf(View descendant, int[] coord,
boolean includeRootScroll) {
- return DragLayer.getDescendantCoordRelativeToParent(descendant, this,
+ return Utilities.getDescendantCoordRelativeToParent(descendant, this,
coord, includeRootScroll);
}
- public static float getDescendantCoordRelativeToParent(View descendant, View root,
- int[] coord, boolean includeRootScroll) {
- ArrayList<View> ancestorChain = new ArrayList<View>();
-
- float[] pt = {coord[0], coord[1]};
-
- View v = descendant;
- while(v != root && v != null) {
- ancestorChain.add(v);
- v = (View) v.getParent();
- }
- ancestorChain.add(root);
-
- float scale = 1.0f;
- int count = ancestorChain.size();
- for (int i = 0; i < count; i++) {
- View v0 = ancestorChain.get(i);
- View v1 = i < count -1 ? ancestorChain.get(i + 1) : null;
-
- // For TextViews, scroll has a meaning which relates to the text position
- // which is very strange... ignore the scroll.
- if (v0 != descendant || includeRootScroll) {
- pt[0] -= v0.getScrollX();
- pt[1] -= v0.getScrollY();
- }
-
- v0.getMatrix().mapPoints(pt);
- pt[0] += v0.getLeft();
- pt[1] += v0.getTop();
- scale *= v0.getScaleX();
- }
-
- coord[0] = (int) Math.round(pt[0]);
- coord[1] = (int) Math.round(pt[1]);
- return scale;
- }
-
/**
* Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
*/
public float mapCoordInSelfToDescendent(View descendant, int[] coord) {
- ArrayList<View> ancestorChain = new ArrayList<View>();
-
- float[] pt = {coord[0], coord[1]};
-
- View v = descendant;
- while(v != this) {
- ancestorChain.add(v);
- v = (View) v.getParent();
- }
- ancestorChain.add(this);
-
- float scale = 1.0f;
- Matrix inverse = new Matrix();
- int count = ancestorChain.size();
- for (int i = count - 1; i >= 0; i--) {
- View ancestor = ancestorChain.get(i);
- View next = i > 0 ? ancestorChain.get(i-1) : null;
-
- pt[0] += ancestor.getScrollX();
- pt[1] += ancestor.getScrollY();
-
- if (next != null) {
- pt[0] -= next.getLeft();
- pt[1] -= next.getTop();
- next.getMatrix().invert(inverse);
- inverse.mapPoints(pt);
- scale *= next.getScaleX();
- }
- }
-
- coord[0] = (int) Math.round(pt[0]);
- coord[1] = (int) Math.round(pt[1]);
- return scale;
+ return Utilities.mapCoordInSelfToDescendent(descendant, this, coord);
}
public void getViewRectRelativeToSelf(View v, Rect r) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7d9ebc0b5..65845b41e 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -3585,6 +3585,8 @@ public class Launcher extends Activity
workspace.addInScreenFromBind(newFolder, item.container, item.screenId, item.cellX,
item.cellY, 1, 1);
break;
+ default:
+ throw new RuntimeException("Invalid Item Type");
}
}
@@ -3724,7 +3726,6 @@ public class Launcher extends Activity
mWorkspaceLoading = false;
if (upgradePath) {
- mWorkspace.saveWorkspaceToDb();
mWorkspace.stripDuplicateApps();
mIntentsOnWorkspaceFromUpgradePath = mWorkspace.stripDuplicateApps();
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 28530e6ac..dd130d2f0 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -265,7 +265,6 @@ public class LauncherModel extends BroadcastReceiver {
}
}
}
- // XXX: Create a new page and add it to the first spot
return null;
}
@@ -294,20 +293,27 @@ public class LauncherModel extends BroadcastReceiver {
Pair<Long, int[]> coords = LauncherModel.findNextAvailableIconSpace(context,
name, launchIntent, startSearchPageIndex);
if (coords == null) {
- // If we can't find a valid position, then just add a new screen.
- // This takes time so we need to re-queue the add until the new
- // page is added.
LauncherAppState appState = LauncherAppState.getInstance();
LauncherProvider lp = appState.getLauncherProvider();
- long screenId = lp.generateNewScreenId();
- // Update the model
- sBgWorkspaceScreens.add(screenId);
- updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
- // Save the screen id for binding in the workspace
- addedWorkspaceScreensFinal.add(screenId);
+
+ // If we can't find a valid position, then just add a new screen.
+ // This takes time so we need to re-queue the add until the new
+ // page is added. Create as many screens as necessary to satisfy
+ // the startSearchPageIndex.
+ int numPagesToAdd = Math.max(1, startSearchPageIndex + 1 -
+ sBgWorkspaceScreens.size());
+ while (numPagesToAdd > 0) {
+ long screenId = lp.generateNewScreenId();
+ // Update the model
+ sBgWorkspaceScreens.add(screenId);
+ updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
+ // Save the screen id for binding in the workspace
+ addedWorkspaceScreensFinal.add(screenId);
+ numPagesToAdd--;
+ }
// Find the coordinate again
coords = LauncherModel.findNextAvailableIconSpace(context,
- a.title.toString(), a.intent, startSearchPageIndex);
+ name, launchIntent, startSearchPageIndex);
}
if (coords == null) {
throw new RuntimeException("Coordinates should not be null");
@@ -1219,7 +1225,6 @@ public class LauncherModel extends BroadcastReceiver {
private boolean mIsLoadingAndBindingWorkspace;
private boolean mStopped;
private boolean mLoadAndBindStepFinished;
- private boolean mIsUpgradePath;
private HashMap<Object, CharSequence> mLabelCache;
@@ -1237,7 +1242,8 @@ public class LauncherModel extends BroadcastReceiver {
return mIsLoadingAndBindingWorkspace;
}
- private void loadAndBindWorkspace() {
+ /** Returns whether this is an upgrade path */
+ private boolean loadAndBindWorkspace() {
mIsLoadingAndBindingWorkspace = true;
// Load the workspace
@@ -1245,18 +1251,20 @@ public class LauncherModel extends BroadcastReceiver {
Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
}
+ boolean isUpgradePath = false;
if (!mWorkspaceLoaded) {
- loadWorkspace();
+ isUpgradePath = loadWorkspace();
synchronized (LoaderTask.this) {
if (mStopped) {
- return;
+ return isUpgradePath;
}
mWorkspaceLoaded = true;
}
}
// Bind the workspace
- bindWorkspace(-1);
+ bindWorkspace(-1, isUpgradePath);
+ return isUpgradePath;
}
private void waitForIdle() {
@@ -1325,13 +1333,15 @@ public class LauncherModel extends BroadcastReceiver {
// Divide the set of loaded items into those that we are binding synchronously, and
// everything else that is to be bound normally (asynchronously).
- bindWorkspace(synchronousBindPage);
+ bindWorkspace(synchronousBindPage, false);
// XXX: For now, continue posting the binding of AllApps as there are other issues that
// arise from that.
onlyBindAllApps();
}
public void run() {
+ boolean isUpgrade = false;
+
synchronized (mLock) {
mIsLoaderTaskRunning = true;
}
@@ -1349,7 +1359,7 @@ public class LauncherModel extends BroadcastReceiver {
? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
}
if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
- loadAndBindWorkspace();
+ isUpgrade = loadAndBindWorkspace();
if (mStopped) {
break keep_running;
@@ -1384,6 +1394,12 @@ public class LauncherModel extends BroadcastReceiver {
sBgDbIconCache.clear();
}
+ // Ensure that all the applications that are in the system are represented on the home
+ // screen.
+ if (!isUpgrade) {
+ verifyApplications();
+ }
+
// Clear out this reference, otherwise we end up holding it until all of the
// callback runnables are done.
mContext = null;
@@ -1434,6 +1450,29 @@ public class LauncherModel extends BroadcastReceiver {
}
}
+ private void verifyApplications() {
+ final Context context = mApp.getContext();
+
+ // Cross reference all the applications in our apps list with items in the workspace
+ ArrayList<ItemInfo> tmpInfos;
+ ArrayList<ApplicationInfo> added = new ArrayList<ApplicationInfo>();
+ synchronized (sBgLock) {
+ for (ApplicationInfo app : mBgAllAppsList.data) {
+ tmpInfos = getItemInfoForComponentName(app.componentName);
+ if (tmpInfos.isEmpty()) {
+ // We are missing an application icon, so add this to the workspace
+ added.add(app);
+ // This is a rare event, so lets log it
+ Log.e(TAG, "Missing Application on load: " + app);
+ }
+ }
+ }
+ if (!added.isEmpty()) {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ addAndBindAddedApps(context, added, cb);
+ }
+ }
+
// check & update map of what's occupied; used to discard overlapping/invalid items
private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item) {
long containerIndex = item.screenId;
@@ -1487,7 +1526,8 @@ public class LauncherModel extends BroadcastReceiver {
return true;
}
- private void loadWorkspace() {
+ /** Returns whether this is an upgradge path */
+ private boolean loadWorkspace() {
final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
final Context context = mContext;
@@ -1497,11 +1537,10 @@ public class LauncherModel extends BroadcastReceiver {
final boolean isSafeMode = manager.isSafeMode();
// Make sure the default workspace is loaded, if needed
- boolean loadOldDb = mApp.getLauncherProvider().shouldLoadOldDb();
- Uri contentUri = loadOldDb ? LauncherSettings.Favorites.OLD_CONTENT_URI :
- LauncherSettings.Favorites.CONTENT_URI;
+ mApp.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);
- mIsUpgradePath = loadOldDb;
+ // Check if we need to do any upgrade-path logic
+ boolean loadedOldDb = mApp.getLauncherProvider().justLoadedOldDb();
synchronized (sBgLock) {
sBgWorkspaceItems.clear();
@@ -1512,7 +1551,7 @@ public class LauncherModel extends BroadcastReceiver {
sBgWorkspaceScreens.clear();
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
-
+ final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
final Cursor c = contentResolver.query(contentUri, null, null, null, null);
// +1 for the hotseat (it can be larger than the workspace)
@@ -1620,10 +1659,6 @@ public class LauncherModel extends BroadcastReceiver {
folderInfo.add(info);
break;
}
- if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
- loadOldDb) {
- info.screenId = permuteScreens(info.screenId);
- }
sBgItemsIdMap.put(info.id, info);
// now that we've loaded everthing re-save it with the
@@ -1663,10 +1698,6 @@ public class LauncherModel extends BroadcastReceiver {
sBgWorkspaceItems.add(folderInfo);
break;
}
- if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
- loadOldDb) {
- folderInfo.screenId = permuteScreens(folderInfo.screenId);
- }
sBgItemsIdMap.put(folderInfo.id, folderInfo);
sBgFolders.put(folderInfo.id, folderInfo);
@@ -1707,11 +1738,6 @@ public class LauncherModel extends BroadcastReceiver {
"CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
continue;
}
- if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
- loadOldDb) {
- appWidgetInfo.screenId =
- permuteScreens(appWidgetInfo.screenId);
- }
appWidgetInfo.container = c.getInt(containerIndex);
// check & update map of what's occupied
@@ -1749,7 +1775,7 @@ public class LauncherModel extends BroadcastReceiver {
}
}
- if (loadOldDb) {
+ if (loadedOldDb) {
long maxScreenId = 0;
// If we're importing we use the old screen order.
for (ItemInfo item: sBgItemsIdMap.values()) {
@@ -1765,6 +1791,15 @@ public class LauncherModel extends BroadcastReceiver {
Collections.sort(sBgWorkspaceScreens);
mApp.getLauncherProvider().updateMaxScreenId(maxScreenId);
updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
+
+ // Update the max item id after we load an old db
+ long maxItemId = 0;
+ // If we're importing we use the old screen order.
+ for (ItemInfo item: sBgItemsIdMap.values()) {
+ maxItemId = Math.max(maxItemId, item.id);
+ }
+ LauncherAppState app = LauncherAppState.getInstance();
+ app.getLauncherProvider().updateMaxItemId(maxItemId);
} else {
Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
final Cursor sc = contentResolver.query(screensUri, null, null, null, null);
@@ -1835,16 +1870,7 @@ public class LauncherModel extends BroadcastReceiver {
}
}
}
- }
-
- // We rearrange the screens from the old launcher
- // 12345 -> 34512
- private long permuteScreens(long screen) {
- if (screen >= 2) {
- return screen - 2;
- } else {
- return screen + 3;
- }
+ return loadedOldDb;
}
/** Filters the set of items who are directly or indirectly (via another container) on the
@@ -2052,7 +2078,7 @@ public class LauncherModel extends BroadcastReceiver {
/**
* Binds all loaded data to actual views on the main thread.
*/
- private void bindWorkspace(int synchronizeBindPage) {
+ private void bindWorkspace(int synchronizeBindPage, final boolean isUpgradePath) {
final long t = SystemClock.uptimeMillis();
Runnable r;
@@ -2144,7 +2170,7 @@ public class LauncherModel extends BroadcastReceiver {
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.finishBindingItems(mIsUpgradePath);
+ callbacks.finishBindingItems(isUpgradePath);
}
// If we're profiling, ensure this is the last thing in the queue.
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index ae227a998..7d090e1fd 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -73,8 +73,10 @@ public class LauncherProvider extends ContentProvider {
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";
+ static final String UPGRADED_FROM_OLD_DATABASE =
+ "UPGRADED_FROM_OLD_DATABASE";
+ static final String EMPTY_DATABASE_CREATED =
+ "EMPTY_DATABASE_CREATED";
static final String DEFAULT_WORKSPACE_RESOURCE_ID =
"DEFAULT_WORKSPACE_RESOURCE_ID";
@@ -90,7 +92,7 @@ public class LauncherProvider extends ContentProvider {
Uri.parse("content://" + AUTHORITY + "/appWidgetReset");
private DatabaseHelper mOpenHelper;
- private static boolean sLoadOldDb;
+ private static boolean sJustLoadedFromOldDb;
@Override
public boolean onCreate() {
@@ -208,6 +210,10 @@ public class LauncherProvider extends ContentProvider {
return mOpenHelper.generateNewItemId();
}
+ public void updateMaxItemId(long id) {
+ mOpenHelper.updateMaxItemId(id);
+ }
+
public long generateNewScreenId() {
return mOpenHelper.generateNewScreenId();
}
@@ -221,21 +227,21 @@ public class LauncherProvider extends ContentProvider {
/**
* @param Should we load the old db for upgrade? first run only.
*/
- synchronized public boolean shouldLoadOldDb() {
+ synchronized public boolean justLoadedOldDb() {
String spKey = LauncherAppState.getSharedPreferencesKey();
SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
- boolean loadOldDb = false || sLoadOldDb;
+ boolean loadedOldDb = false || sJustLoadedFromOldDb;
- sLoadOldDb = false;
- if (sp.getBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, false)) {
+ sJustLoadedFromOldDb = false;
+ if (sp.getBoolean(UPGRADED_FROM_OLD_DATABASE, false)) {
SharedPreferences.Editor editor = sp.edit();
- editor.remove(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED);
+ editor.remove(UPGRADED_FROM_OLD_DATABASE);
editor.commit();
- loadOldDb = true;
+ loadedOldDb = true;
}
- return loadOldDb;
+ return loadedOldDb;
}
/**
@@ -245,7 +251,7 @@ public class LauncherProvider extends ContentProvider {
String spKey = LauncherAppState.getSharedPreferencesKey();
SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
- if (sp.getBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, false)) {
+ if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
int workspaceResId = origWorkspaceResId;
// Use default workspace resource if none provided
@@ -255,16 +261,21 @@ public class LauncherProvider extends ContentProvider {
// Populate favorites table with initial favorites
SharedPreferences.Editor editor = sp.edit();
- editor.remove(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED);
+ editor.remove(EMPTY_DATABASE_CREATED);
if (origWorkspaceResId != 0) {
editor.putInt(DEFAULT_WORKSPACE_RESOURCE_ID, origWorkspaceResId);
}
mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(), workspaceResId);
+ mOpenHelper.setFlagJustLoadedOldDb();
editor.commit();
}
}
+ private static interface ContentValuesCallback {
+ public void onRow(ContentValues values);
+ }
+
private static class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG_FAVORITES = "favorites";
private static final String TAG_FAVORITE = "favorite";
@@ -341,10 +352,32 @@ public class LauncherProvider extends ContentProvider {
sendAppWidgetResetNotify();
}
- if (!convertDatabase(db)) {
- // Set a shared pref so that we know we need to load the default workspace later
- setFlagToLoadDefaultWorkspaceLater();
+ // Try converting the old database
+ ContentValuesCallback permuteScreensCb = new ContentValuesCallback() {
+ public void onRow(ContentValues values) {
+ int container = values.getAsInteger(LauncherSettings.Favorites.CONTAINER);
+ if (container == Favorites.CONTAINER_DESKTOP) {
+ int screen = values.getAsInteger(LauncherSettings.Favorites.SCREEN);
+ screen = (int) upgradeLauncherDb_permuteScreens(screen);
+ values.put(LauncherSettings.Favorites.SCREEN, screen);
+ }
+ }
+ };
+ Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
+ "/old_favorites?notify=true");
+ if (!convertDatabase(db, uri, permuteScreensCb, true)) {
+ // Try and upgrade from the Launcher2 db
+ uri = LauncherSettings.Favorites.OLD_CONTENT_URI;
+ if (!convertDatabase(db, uri, permuteScreensCb, false)) {
+ // If we fail, then set a flag to load the default workspace
+ setFlagEmptyDbCreated();
+ return;
+ }
}
+ // Right now, in non-default workspace cases, we want to run the final
+ // upgrade code (ie. to fix workspace screen indices -> ids, etc.), so
+ // set that flag too.
+ setFlagJustLoadedOldDb();
}
private void addWorkspacesTable(SQLiteDatabase db) {
@@ -354,20 +387,39 @@ public class LauncherProvider extends ContentProvider {
");");
}
- private void setFlagToLoadDefaultWorkspaceLater() {
+ private void setFlagJustLoadedOldDb() {
String spKey = LauncherAppState.getSharedPreferencesKey();
SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
- editor.putBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, true);
+ editor.putBoolean(UPGRADED_FROM_OLD_DATABASE, true);
+ editor.putBoolean(EMPTY_DATABASE_CREATED, false);
editor.commit();
}
- private boolean convertDatabase(SQLiteDatabase db) {
+ private void setFlagEmptyDbCreated() {
+ String spKey = LauncherAppState.getSharedPreferencesKey();
+ SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sp.edit();
+ editor.putBoolean(EMPTY_DATABASE_CREATED, true);
+ editor.putBoolean(UPGRADED_FROM_OLD_DATABASE, false);
+ editor.commit();
+ }
+
+ // We rearrange the screens from the old launcher
+ // 12345 -> 34512
+ private long upgradeLauncherDb_permuteScreens(long screen) {
+ if (screen >= 2) {
+ return screen - 2;
+ } else {
+ return screen + 3;
+ }
+ }
+
+ private boolean convertDatabase(SQLiteDatabase db, Uri uri,
+ ContentValuesCallback cb, boolean deleteRows) {
if (LOGD) Log.d(TAG, "converting database from an older format, but not onUpgrade");
boolean converted = false;
- final Uri uri = Uri.parse("content://" + Settings.AUTHORITY +
- "/old_favorites?notify=true");
final ContentResolver resolver = mContext.getContentResolver();
Cursor cursor = null;
@@ -378,28 +430,33 @@ public class LauncherProvider extends ContentProvider {
}
// We already have a favorites database in the old provider
- if (cursor != null && cursor.getCount() > 0) {
+ if (cursor != null) {
try {
- converted = copyFromCursor(db, cursor) > 0;
+ if (cursor.getCount() > 0) {
+ converted = copyFromCursor(db, cursor, cb) > 0;
+ if (converted && deleteRows) {
+ resolver.delete(uri, null, null);
+ }
+ }
} finally {
cursor.close();
}
-
- if (converted) {
- resolver.delete(uri, null, null);
- }
}
if (converted) {
// Convert widgets from this import into widgets
if (LOGD) Log.d(TAG, "converted and now triggering widget upgrade");
convertWidgets(db);
+
+ // Update max item id
+ mMaxItemId = initializeMaxItemId(db);
+ if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId);
}
return converted;
}
- private int copyFromCursor(SQLiteDatabase db, Cursor c) {
+ private int copyFromCursor(SQLiteDatabase db, Cursor c, ContentValuesCallback cb) {
final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
@@ -434,23 +491,28 @@ public class LauncherProvider extends ContentProvider {
values.put(LauncherSettings.Favorites.CELLY, c.getInt(cellYIndex));
values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex));
values.put(LauncherSettings.Favorites.DISPLAY_MODE, c.getInt(displayModeIndex));
+ if (cb != null) {
+ cb.onRow(values);
+ }
rows[i++] = values;
}
- db.beginTransaction();
int total = 0;
- try {
- int numValues = rows.length;
- for (i = 0; i < numValues; i++) {
- if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i]) < 0) {
- return 0;
- } else {
- total++;
+ if (i > 0) {
+ db.beginTransaction();
+ try {
+ int numValues = rows.length;
+ for (i = 0; i < numValues; i++) {
+ if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i]) < 0) {
+ return 0;
+ } else {
+ total++;
+ }
}
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
}
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
}
return total;
@@ -458,7 +520,7 @@ public class LauncherProvider extends ContentProvider {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- if (LOGD) Log.d(TAG, "onUpgrade triggered");
+ if (LOGD) Log.d(TAG, "onUpgrade triggered: " + oldVersion);
int version = oldVersion;
if (version < 3) {
@@ -558,7 +620,7 @@ public class LauncherProvider extends ContentProvider {
// This will never happen in the wild, but when we switch to using workspace
// screen ids, redo the import from old launcher.
- sLoadOldDb = true;
+ sJustLoadedFromOldDb = true;
addWorkspacesTable(db);
version = 13;
@@ -722,6 +784,10 @@ public class LauncherProvider extends ContentProvider {
return mMaxItemId;
}
+ public void updateMaxItemId(long id) {
+ mMaxItemId = id + 1;
+ }
+
private long initializeMaxItemId(SQLiteDatabase db) {
Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null);
@@ -861,6 +927,10 @@ public class LauncherProvider extends ContentProvider {
c.close();
}
}
+
+ // Update max item id
+ mMaxItemId = initializeMaxItemId(db);
+ if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId);
}
private static final void beginDocument(XmlPullParser parser, String firstElementName)
@@ -1018,6 +1088,11 @@ public class LauncherProvider extends ContentProvider {
Log.w(TAG, "Got exception parsing favorites.", e);
}
+ // Update the max item id after we have loaded the database
+ if (mMaxItemId == -1) {
+ mMaxItemId = initializeMaxItemId(db);
+ }
+
return i;
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index aaff58886..d53fd751f 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -983,7 +983,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// Check if the right edge of the page is in the viewport
mTmpIntPoint[0] = currPage.getMeasuredWidth();
- DragLayer.getDescendantCoordRelativeToParent(currPage, this, mTmpIntPoint, false);
+ Utilities.getDescendantCoordRelativeToParent(currPage, this, mTmpIntPoint, false);
if (mTmpIntPoint[0] < 0) {
break;
}
@@ -993,7 +993,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// Check if the left edge of the page is in the viewport
mTmpIntPoint[0] = 0;
- DragLayer.getDescendantCoordRelativeToParent(currPage, this, mTmpIntPoint, false);
+ Utilities.getDescendantCoordRelativeToParent(currPage, this, mTmpIntPoint, false);
if (mTmpIntPoint[0] >= viewportWidth) {
break;
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 0cc29faa3..cc22bb5db 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -25,6 +25,7 @@ import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.PorterDuff;
@@ -33,6 +34,10 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PaintDrawable;
import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
import com.android.launcher3.R;
@@ -232,6 +237,96 @@ final class Utilities {
}
}
+ /**
+ * Given a coordinate relative to the descendant, find the coordinate in a parent view's
+ * coordinates.
+ *
+ * @param descendant The descendant to which the passed coordinate is relative.
+ * @param root The root view to make the coordinates relative to.
+ * @param coord The coordinate that we want mapped.
+ * @param includeRootScroll Whether or not to account for the scroll of the descendant:
+ * sometimes this is relevant as in a child's coordinates within the descendant.
+ * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
+ * this scale factor is assumed to be equal in X and Y, and so if at any point this
+ * assumption fails, we will need to return a pair of scale factors.
+ */
+ public static float getDescendantCoordRelativeToParent(View descendant, View root,
+ int[] coord, boolean includeRootScroll) {
+ ArrayList<View> ancestorChain = new ArrayList<View>();
+
+ float[] pt = {coord[0], coord[1]};
+
+ View v = descendant;
+ while(v != root && v != null) {
+ ancestorChain.add(v);
+ v = (View) v.getParent();
+ }
+ ancestorChain.add(root);
+
+ float scale = 1.0f;
+ int count = ancestorChain.size();
+ for (int i = 0; i < count; i++) {
+ View v0 = ancestorChain.get(i);
+ View v1 = i < count -1 ? ancestorChain.get(i + 1) : null;
+
+ // For TextViews, scroll has a meaning which relates to the text position
+ // which is very strange... ignore the scroll.
+ if (v0 != descendant || includeRootScroll) {
+ pt[0] -= v0.getScrollX();
+ pt[1] -= v0.getScrollY();
+ }
+
+ v0.getMatrix().mapPoints(pt);
+ pt[0] += v0.getLeft();
+ pt[1] += v0.getTop();
+ scale *= v0.getScaleX();
+ }
+
+ coord[0] = (int) Math.round(pt[0]);
+ coord[1] = (int) Math.round(pt[1]);
+ return scale;
+ }
+
+ /**
+ * Inverse of {@link #getDescendantCoordRelativeToSelf(View, int[])}.
+ */
+ public static float mapCoordInSelfToDescendent(View descendant, View root,
+ int[] coord) {
+ ArrayList<View> ancestorChain = new ArrayList<View>();
+
+ float[] pt = {coord[0], coord[1]};
+
+ View v = descendant;
+ while(v != root) {
+ ancestorChain.add(v);
+ v = (View) v.getParent();
+ }
+ ancestorChain.add(root);
+
+ float scale = 1.0f;
+ Matrix inverse = new Matrix();
+ int count = ancestorChain.size();
+ for (int i = count - 1; i >= 0; i--) {
+ View ancestor = ancestorChain.get(i);
+ View next = i > 0 ? ancestorChain.get(i-1) : null;
+
+ pt[0] += ancestor.getScrollX();
+ pt[1] += ancestor.getScrollY();
+
+ if (next != null) {
+ pt[0] -= next.getLeft();
+ pt[1] -= next.getTop();
+ next.getMatrix().invert(inverse);
+ inverse.mapPoints(pt);
+ scale *= next.getScaleX();
+ }
+ }
+
+ coord[0] = (int) Math.round(pt[0]);
+ coord[1] = (int) Math.round(pt[1]);
+ return scale;
+ }
+
private static void initStatics(Context context) {
final Resources resources = context.getResources();
final DisplayMetrics metrics = resources.getDisplayMetrics();
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index b8ef6b117..4f8f8d177 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1330,7 +1330,13 @@ public class Workspace extends SmoothPagedView
progress = Math.max(0, progress);
setBackgroundAlpha(progress * 0.8f);
- float transY = progress * (getViewportHeight() - getPageIndicator().getTop());
+ float height = getViewportHeight();
+ if (getPageIndicator() != null) {
+ height -= getPageIndicator().getTop();
+ } else if (mLauncher.getHotseat() != null) {
+ height -= mLauncher.getHotseat().getTop();
+ }
+ float transY = progress * height;
if (mLauncher.getHotseat() != null) {
mLauncher.getHotseat().setTranslationY(transY);