Merge "Remove unnecessary lock"
diff --git a/res/layout/apps_customize_pane.xml b/res/layout/apps_customize_pane.xml
index 9d86c48..00c87cb 100644
--- a/res/layout/apps_customize_pane.xml
+++ b/res/layout/apps_customize_pane.xml
@@ -79,6 +79,7 @@
launcher:maxGap="@dimen/workspace_max_gap" />
<include
+ style="@style/AppsCustomizeScrollTrack"
android:id="@+id/paged_view_indicator_track"
layout="@layout/scroll_indicator_track"
android:layout_width="match_parent"
diff --git a/res/values-large/styles.xml b/res/values-large/styles.xml
index 254ecb8..25b8195 100644
--- a/res/values-large/styles.xml
+++ b/res/values-large/styles.xml
@@ -18,6 +18,11 @@
-->
<resources>
+<!-- AppsCustomize -->
+ <style name="AppsCustomizeScrollTrack">
+ <item name="android:visibility">gone</item>
+ </style>
+
<!-- Workspace -->
<style name="ScrollIndicatorTrack">
<item name="android:visibility">gone</item>
diff --git a/res/values/config.xml b/res/values/config.xml
index a5d7b91..497011c 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -63,7 +63,7 @@
<!-- Parameters controlling the animation for when an item is dropped on the home screen,
and it animates from its old position to the new one. -->
- <integer name="config_dropAnimMaxDuration">600</integer>
+ <integer name="config_dropAnimMaxDuration">500</integer>
<!-- The duration of the UserFolder opening and closing animation -->
<integer name="config_folderAnimDuration">120</integer>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 45e85e1..06f6ed0 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -29,6 +29,10 @@
<item name="android:windowNoTitle">true</item>
</style>
+ <style name="AppsCustomizeScrollTrack">
+ <item name="android:visibility">visible</item>
+ </style>
+
<style name="AnimationPreview">
<item name="android:windowEnterAnimation">@anim/fade_in_fast</item>
<item name="android:windowExitAnimation">@anim/fade_out_fast</item>
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index ced46c9..33472ea 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -1137,6 +1137,7 @@
addAppsWithoutInvalidate(list);
invalidatePageData();
}
+
@Override
public void reset() {
if (mContentType != ContentType.Applications) {
@@ -1144,7 +1145,7 @@
AppsCustomizeTabHost tabs = (AppsCustomizeTabHost)
mLauncher.findViewById(R.id.apps_customize_pane);
tabs.setCurrentTabByTag(tabs.getTabTagForContentType(ContentType.Applications));
- } else {
+ } else if (getCurrentPage() != 0) {
setCurrentPage(0);
invalidatePageData();
}
diff --git a/src/com/android/launcher2/ButtonDropTarget.java b/src/com/android/launcher2/ButtonDropTarget.java
index e3da860..f87889c 100644
--- a/src/com/android/launcher2/ButtonDropTarget.java
+++ b/src/com/android/launcher2/ButtonDropTarget.java
@@ -90,4 +90,8 @@
public DropTarget getDropTargetDelegate(DragObject d) {
return null;
}
+
+ public void getLocationInDragLayer(int[] loc) {
+ mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
+ }
}
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index f890808..b8515fc 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -706,8 +706,6 @@
// The child hit rect is relative to the CellLayoutChildren parent, so we need to
// offset that by this CellLayout's padding to test an (x,y) point that is relative
// to this view.
- final int tmpXY[] = mTmpXY;
- child.getLocationOnScreen(tmpXY);
frame.offset(mPaddingLeft, mPaddingTop);
if (frame.contains(x, y)) {
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 9a6335b..f6058a0 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -61,7 +61,7 @@
static final int SCROLL_LEFT = 0;
static final int SCROLL_RIGHT = 1;
- private Context mContext;
+ private Launcher mLauncher;
private Handler mHandler;
private final Vibrator mVibrator = new Vibrator();
@@ -78,9 +78,6 @@
/** Y coordinate of the down event. */
private int mMotionDownY;
- /** Info about the screen for clamping. */
- private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
-
/** the area at the edge of the screen that makes the workspace go left
* or right while you're dragging.
*/
@@ -139,10 +136,10 @@
*
* @param context The application's context.
*/
- public DragController(Context context) {
- mContext = context;
+ public DragController(Launcher launcher) {
+ mLauncher = launcher;
mHandler = new Handler();
- mScrollZone = context.getResources().getDimensionPixelSize(R.dimen.scroll_zone);
+ mScrollZone = launcher.getResources().getDimensionPixelSize(R.dimen.scroll_zone);
}
public boolean dragging() {
@@ -183,11 +180,11 @@
}
int[] loc = mCoordinatesTemp;
- v.getLocationOnScreen(loc);
- int screenX = loc[0];
- int screenY = loc[1];
+ mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
+ int dragLayerX = loc[0];
+ int dragLayerY = loc[1];
- startDrag(b, screenX, screenY, source, dragInfo, dragAction, dragRegion);
+ startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, dragRegion);
b.recycle();
if (dragAction == DRAG_ACTION_MOVE) {
@@ -210,11 +207,11 @@
public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo, int dragAction,
Rect dragRegion) {
int[] loc = mCoordinatesTemp;
- v.getLocationOnScreen(loc);
- int screenX = loc[0];
- int screenY = loc[1];
+ mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
+ int dragLayerX = loc[0];
+ int dragLayerY = loc[1];
- startDrag(bmp, screenX, screenY, source, dragInfo, dragAction, dragRegion);
+ startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, dragRegion);
if (dragAction == DRAG_ACTION_MOVE) {
v.setVisibility(View.GONE);
@@ -226,16 +223,16 @@
*
* @param b The bitmap to display as the drag image. It will be re-scaled to the
* enlarged size.
- * @param screenX The x position on screen of the left-top of the bitmap.
- * @param screenY The y position on screen of the left-top of the bitmap.
+ * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
+ * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
* @param source An object representing where the drag originated
* @param dragInfo The data associated with the object that is being dragged
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
* {@link #DRAG_ACTION_COPY}
*/
- public void startDrag(Bitmap b, int screenX, int screenY,
+ public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
DragSource source, Object dragInfo, int dragAction) {
- startDrag(b, screenX, screenY, source, dragInfo, dragAction, null);
+ startDrag(b, dragLayerX, dragLayerY, source, dragInfo, dragAction, null);
}
/**
@@ -243,8 +240,8 @@
*
* @param b The bitmap to display as the drag image. It will be re-scaled to the
* enlarged size.
- * @param screenX The x position on screen of the left-top of the bitmap.
- * @param screenY The y position on screen of the left-top of the bitmap.
+ * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
+ * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
* @param source An object representing where the drag originated
* @param dragInfo The data associated with the object that is being dragged
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
@@ -252,7 +249,7 @@
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
* Makes dragging feel more precise, e.g. you can clip out a transparent border
*/
- public void startDrag(Bitmap b, int screenX, int screenY,
+ public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,
DragSource source, Object dragInfo, int dragAction, Rect dragRegion) {
if (PROFILE_DRAWING_DURING_DRAG) {
android.os.Debug.startMethodTracing("Launcher");
@@ -261,7 +258,7 @@
// Hide soft keyboard, if visible
if (mInputMethodManager == null) {
mInputMethodManager = (InputMethodManager)
- mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+ mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE);
}
mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
@@ -269,8 +266,8 @@
listener.onDragStart(source, dragInfo, dragAction);
}
- final int registrationX = ((int)mMotionDownX) - screenX;
- final int registrationY = ((int)mMotionDownY) - screenY;
+ final int registrationX = mMotionDownX - dragLayerX;
+ final int registrationY = mMotionDownY - dragLayerY;
final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
@@ -278,14 +275,14 @@
mDragging = true;
mDragObject.dragComplete = false;
- mDragObject.xOffset = mMotionDownX - (screenX + dragRegionLeft);
- mDragObject.yOffset = mMotionDownY - (screenY + dragRegionTop);
+ mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
+ mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
mDragObject.dragSource = source;
mDragObject.dragInfo = dragInfo;
mVibrator.vibrate(VIBRATE_DURATION);
- final DragView dragView = mDragObject.dragView = new DragView(mContext, b, registrationX,
+ final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,
registrationY, 0, 0, b.getWidth(), b.getHeight());
final DragSource dragSource = source;
@@ -299,9 +296,8 @@
dragView.setDragRegion(new Rect(dragRegion));
}
- dragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY);
-
- handleMoveEvent((int) mMotionDownX, (int) mMotionDownY);
+ dragView.show(mMotionDownX, mMotionDownY);
+ handleMoveEvent(mMotionDownX, mMotionDownY);
}
/**
@@ -398,25 +394,21 @@
}
final int action = ev.getAction();
- if (action == MotionEvent.ACTION_DOWN) {
- recordScreenSize();
- }
-
- final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels);
- final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels);
+ final int dragLayerX = (int) ev.getX();
+ final int dragLayerY = (int) ev.getY();
switch (action) {
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_DOWN:
// Remember location of down touch
- mMotionDownX = screenX;
- mMotionDownY = screenY;
+ mMotionDownX = dragLayerX;
+ mMotionDownY = dragLayerY;
mLastDropTarget = null;
break;
case MotionEvent.ACTION_UP:
if (mDragging) {
- drop(screenX, screenY);
+ drop(dragLayerX, dragLayerY);
}
endDrag();
break;
@@ -475,7 +467,7 @@
// After a scroll, the touch point will still be in the scroll region.
// Rather than scrolling immediately, require a bit of twiddling to scroll again
- final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop();
+ final int slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop();
mDistanceSinceScroll +=
Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2));
mLastTouch[0] = x;
@@ -514,16 +506,16 @@
}
final int action = ev.getAction();
- final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels);
- final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels);
+ final int dragLayerX = (int) ev.getX();
+ final int dragLayerY = (int) ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Remember where the motion event started
- mMotionDownX = screenX;
- mMotionDownY = screenY;
+ mMotionDownX = dragLayerX;
+ mMotionDownY = dragLayerY;
- if ((screenX < mScrollZone) || (screenX > mScrollView.getWidth() - mScrollZone)) {
+ if ((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) {
mScrollState = SCROLL_WAITING_IN_ZONE;
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
} else {
@@ -531,15 +523,15 @@
}
break;
case MotionEvent.ACTION_MOVE:
- handleMoveEvent(screenX, screenY);
+ handleMoveEvent(dragLayerX, dragLayerY);
break;
case MotionEvent.ACTION_UP:
// Ensure that we've processed a move event at the current pointer location.
- handleMoveEvent(screenX, screenY);
+ handleMoveEvent(dragLayerX, dragLayerY);
mHandler.removeCallbacks(mScrollRunnable);
if (mDragging) {
- drop(screenX, screenY);
+ drop(dragLayerX, dragLayerY);
}
endDrag();
break;
@@ -581,8 +573,8 @@
target.getHitRect(r);
- // Convert the hit rect to screen coordinates
- target.getLocationOnScreen(dropCoordinates);
+ // Convert the hit rect to DragLayer coordinates
+ target.getLocationInDragLayer(dropCoordinates);
r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop());
mDragObject.x = x;
@@ -591,7 +583,7 @@
DropTarget delegate = target.getDropTargetDelegate(mDragObject);
if (delegate != null) {
target = delegate;
- target.getLocationOnScreen(dropCoordinates);
+ target.getLocationInDragLayer(dropCoordinates);
}
// Make dropCoordinates relative to the DropTarget
@@ -604,28 +596,6 @@
return null;
}
- /**
- * Get the screen size so we can clamp events to the screen size so even if
- * you drag off the edge of the screen, we find something.
- */
- private void recordScreenSize() {
- ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
- .getDefaultDisplay().getMetrics(mDisplayMetrics);
- }
-
- /**
- * Clamp val to be >= min and < max.
- */
- private static int clamp(int val, int min, int max) {
- if (val < min) {
- return min;
- } else if (val >= max) {
- return max - 1;
- } else {
- return val;
- }
- }
-
public void setDragScoller(DragScroller scroller) {
mDragScroller = scroller;
}
@@ -672,7 +642,7 @@
/**
* Specifies the delete region. We won't scroll on touch events over the delete region.
*
- * @param region The rectangle in screen coordinates of the delete region.
+ * @param region The rectangle in DragLayer coordinates of the delete region.
*/
void setDeleteRegion(RectF region) {
mDeleteRegion = region;
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index d76b902..dfd8160 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -18,12 +18,12 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.util.AttributeSet;
@@ -33,9 +33,7 @@
import android.view.ViewParent;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
-import android.widget.ImageView;
import com.android.launcher.R;
@@ -58,8 +56,10 @@
// Variables relating to animation of views after drop
private ValueAnimator mDropAnim = null;
- private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f);
+ private ValueAnimator mFadeOutAnim = null;
+ private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
private View mDropView = null;
+
private int[] mDropViewPos = new int[2];
private float mDropViewScale;
private float mDropViewAlpha;
@@ -168,14 +168,16 @@
}
public void getDescendantRectRelativeToSelf(View descendant, Rect r) {
- descendant.getHitRect(r);
mTmpXY[0] = 0;
mTmpXY[1] = 0;
getDescendantCoordRelativeToSelf(descendant, mTmpXY);
- r.offset(mTmpXY[0], mTmpXY[1]);
+ r.set(mTmpXY[0], mTmpXY[1],
+ mTmpXY[0] + descendant.getWidth(), mTmpXY[1] + descendant.getHeight());
}
- public void getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
+ private void getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
+ coord[0] += descendant.getLeft();
+ coord[1] += descendant.getTop();
ViewParent viewParent = descendant.getParent();
while (viewParent instanceof View && viewParent != this) {
final View view = (View)viewParent;
@@ -185,13 +187,19 @@
}
}
+ public void getLocationInDragLayer(View child, int[] loc) {
+ loc[0] = 0;
+ loc[1] = 0;
+ getDescendantCoordRelativeToSelf(child, loc);
+ }
+
public void getViewRectRelativeToSelf(View v, Rect r) {
int[] loc = new int[2];
- getLocationOnScreen(loc);
+ getLocationInWindow(loc);
int x = loc[0];
int y = loc[1];
- v.getLocationOnScreen(loc);
+ v.getLocationInWindow(loc);
int vX = loc[0];
int vY = loc[1];
@@ -205,21 +213,6 @@
return mDragController.dispatchUnhandledMove(focused, direction);
}
- public View createDragView(Bitmap b, int xPos, int yPos) {
- ImageView imageView = new ImageView(mContext);
- imageView.setImageBitmap(b);
- imageView.setX(xPos);
- imageView.setY(yPos);
- addView(imageView, b.getWidth(), b.getHeight());
-
- return imageView;
- }
-
- public View createDragView(View v) {
- v.getLocationOnScreen(mTmpXY);
- return createDragView(mDragController.getViewBitmap(v), mTmpXY[0], mTmpXY[1]);
- }
-
public static class LayoutParams extends FrameLayout.LayoutParams {
public int x, y;
public boolean customPosition = false;
@@ -320,29 +313,40 @@
int coord[] = new int[2];
coord[0] = lp.x;
coord[1] = lp.y;
- getDescendantCoordRelativeToSelf(child, coord);
+ // Since the child hasn't necessarily been laid out, we force the lp to be updated with
+ // the correct coordinates and use these to determine the final location
+ getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
+ int toX = coord[0] - (dragView.getWidth() - child.getMeasuredWidth()) / 2;
+ int toY = coord[1] - (dragView.getHeight() - child.getMeasuredHeight()) / 2;
final int fromX = r.left + (dragView.getWidth() - child.getMeasuredWidth()) / 2;
final int fromY = r.top + (dragView.getHeight() - child.getMeasuredHeight()) / 2;
child.setVisibility(INVISIBLE);
- animateViewIntoPosition(child, fromX, fromY, coord[0], coord[1]);
+ child.setAlpha(0);
+ Runnable onCompleteRunnable = new Runnable() {
+ public void run() {
+ child.setVisibility(VISIBLE);
+ ObjectAnimator oa = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f);
+ oa.setDuration(60);
+ oa.start();
+ }
+ };
+ animateViewIntoPosition(dragView, fromX, fromY, toX, toY, onCompleteRunnable, true);
}
private void animateViewIntoPosition(final View view, final int fromX, final int fromY,
- final int toX, final int toY) {
- Rect from = new Rect(fromX, fromY, fromX + view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
+ final int toX, final int toY, Runnable onCompleteRunnable, boolean fadeOut) {
+ Rect from = new Rect(fromX, fromY, fromX +
+ view.getMeasuredWidth(), fromY + view.getMeasuredHeight());
Rect to = new Rect(toX, toY, toX + view.getMeasuredWidth(), toY + view.getMeasuredHeight());
- animateView(view, from, to, 1f, -1);
- }
+ animateView(view, from, to, 1f, 1.0f, -1, null, null, onCompleteRunnable, true);
- public void animateView(final View view, final Rect from, final Rect to,
- final float finalAlpha, int duration) {
- animateView(view, from, to, finalAlpha, 1.0f, duration, null, null);
}
public void animateView(final View view, final Rect from, final Rect to, final float finalAlpha,
final float finalScale, int duration, final Interpolator motionInterpolator,
- final Interpolator alphaInterpolator) {
+ final Interpolator alphaInterpolator, final Runnable onCompleteRunnable,
+ final boolean fadeOut) {
// Calculate the duration of the animation based on the object's distance
final float dist = (float) Math.sqrt(Math.pow(to.left - from.left, 2) +
Math.pow(to.top - from.top, 2));
@@ -353,19 +357,19 @@
if (duration < 0) {
duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
if (dist < maxDist) {
- duration *= mQuintEaseOutInterpolator.getInterpolation(dist / maxDist);
+ duration *= mCubicEaseOutInterpolator.getInterpolation(dist / maxDist);
}
}
if (mDropAnim != null) {
- mDropAnim.end();
+ mDropAnim.cancel();
}
mDropView = view;
final float initialAlpha = view.getAlpha();
mDropAnim = new ValueAnimator();
if (alphaInterpolator == null || motionInterpolator == null) {
- mDropAnim.setInterpolator(mQuintEaseOutInterpolator);
+ mDropAnim.setInterpolator(mCubicEaseOutInterpolator);
}
mDropAnim.setDuration(duration);
@@ -395,8 +399,12 @@
});
mDropAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
- if (mDropView != null) {
- mDropView.setVisibility(View.VISIBLE);
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+ if (fadeOut) {
+ fadeOutDragView();
+ } else {
mDropView = null;
}
}
@@ -404,6 +412,29 @@
mDropAnim.start();
}
+ private void fadeOutDragView() {
+ mFadeOutAnim = new ValueAnimator();
+ mFadeOutAnim.setDuration(150);
+ mFadeOutAnim.setFloatValues(0f, 1f);
+ mFadeOutAnim.removeAllUpdateListeners();
+ mFadeOutAnim.addUpdateListener(new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float percent = (Float) animation.getAnimatedValue();
+ mDropViewAlpha = 1 - percent;
+ int width = mDropView.getMeasuredWidth();
+ int height = mDropView.getMeasuredHeight();
+ invalidate(mDropViewPos[0], mDropViewPos[1],
+ mDropViewPos[0] + width, mDropViewPos[1] + height);
+ }
+ });
+ mFadeOutAnim.addListener(new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animation) {
+ mDropView = null;
+ }
+ });
+ mFadeOutAnim.start();
+ }
+
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index d4dc785..aff3d42 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -19,18 +19,14 @@
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
-import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.IBinder;
-import android.view.Gravity;
import android.view.View;
-import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.animation.DecelerateInterpolator;
@@ -44,13 +40,13 @@
private int mRegistrationY;
private Rect mDragRegion = null;
+ private DragLayer mDragLayer = null;
ValueAnimator mAnim;
private float mOffsetX = 0.0f;
private float mOffsetY = 0.0f;
- private WindowManager.LayoutParams mLayoutParams;
- private WindowManager mWindowManager;
+ private DragLayer.LayoutParams mLayoutParams;
/**
* A callback to be called the first time this view is drawn.
@@ -65,20 +61,19 @@
* The registration point is the point inside our view that the touch events should
* be centered upon.
*
- * @param context A context
+ * @param launcher The Launcher instance
* @param bitmap The view that we're dragging around. We scale it up when we draw it.
* @param registrationX The x coordinate of the registration point.
* @param registrationY The y coordinate of the registration point.
*/
- public DragView(Context context, Bitmap bitmap, int registrationX, int registrationY,
+ public DragView(Launcher launcher, Bitmap bitmap, int registrationX, int registrationY,
int left, int top, int width, int height) {
- super(context);
+ super(launcher);
+ mDragLayer = launcher.getDragLayer();
final Resources res = getResources();
final int dragScale = res.getInteger(R.integer.config_dragViewExtraPixels);
- mWindowManager = WindowManagerImpl.getDefault();
-
Matrix scale = new Matrix();
final float scaleFactor = (width + dragScale) / width;
if (scaleFactor != 1.0f) {
@@ -106,10 +101,10 @@
if (getParent() == null) {
animation.cancel();
} else {
- WindowManager.LayoutParams lp = mLayoutParams;
+ DragLayer.LayoutParams lp = mLayoutParams;
lp.x += deltaX;
lp.y += deltaY;
- mWindowManager.updateViewLayout(DragView.this, lp);
+ mDragLayer.requestLayout();
}
}
});
@@ -209,58 +204,45 @@
* Create a window containing this view and show it.
*
* @param windowToken obtained from v.getWindowToken() from one of your views
- * @param touchX the x coordinate the user touched in screen coordinates
- * @param touchY the y coordinate the user touched in screen coordinates
+ * @param touchX the x coordinate the user touched in DragLayer coordinates
+ * @param touchY the y coordinate the user touched in DragLayer coordinates
*/
- public void show(IBinder windowToken, int touchX, int touchY) {
- WindowManager.LayoutParams lp;
- int pixelFormat;
-
- pixelFormat = PixelFormat.TRANSLUCENT;
-
- lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- touchX - mRegistrationX, touchY - mRegistrationY,
- WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- /*| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM*/,
- pixelFormat);
-// lp.token = mStatusBarView.getWindowToken();
- lp.gravity = Gravity.LEFT | Gravity.TOP;
- lp.token = windowToken;
- lp.setTitle("DragView");
+ public void show(int touchX, int touchY) {
+ mDragLayer.addView(this);
+ DragLayer.LayoutParams lp = new DragLayer.LayoutParams(0, 0);
+ lp.width = mBitmap.getWidth();
+ lp.height = mBitmap.getHeight();
+ lp.x = touchX - mRegistrationX;
+ lp.y = touchY - mRegistrationY;
+ lp.customPosition = true;
+ setLayoutParams(lp);
mLayoutParams = lp;
-
- mWindowManager.addView(this, lp);
-
mAnim.start();
}
/**
* Move the window containing this view.
*
- * @param touchX the x coordinate the user touched in screen coordinates
- * @param touchY the y coordinate the user touched in screen coordinates
+ * @param touchX the x coordinate the user touched in DragLayer coordinates
+ * @param touchY the y coordinate the user touched in DragLayer coordinates
*/
void move(int touchX, int touchY) {
- WindowManager.LayoutParams lp = mLayoutParams;
+ DragLayer.LayoutParams lp = mLayoutParams;
lp.x = touchX - mRegistrationX + (int) mOffsetX;
lp.y = touchY - mRegistrationY + (int) mOffsetY;
- mWindowManager.updateViewLayout(this, lp);
+ mDragLayer.requestLayout();
}
void remove() {
post(new Runnable() {
public void run() {
- mWindowManager.removeView(DragView.this);
+ mDragLayer.removeView(DragView.this);
}
});
}
int[] getPosition(int[] result) {
- WindowManager.LayoutParams lp = mLayoutParams;
+ DragLayer.LayoutParams lp = mLayoutParams;
if (result == null) result = new int[2];
result[0] = lp.x;
result[1] = lp.y;
diff --git a/src/com/android/launcher2/DropTarget.java b/src/com/android/launcher2/DropTarget.java
index 6e18479..0712420 100644
--- a/src/com/android/launcher2/DropTarget.java
+++ b/src/com/android/launcher2/DropTarget.java
@@ -120,7 +120,7 @@
// These methods are implemented in Views
void getHitRect(Rect outRect);
- void getLocationOnScreen(int[] loc);
+ void getLocationInDragLayer(int[] loc);
int getLeft();
int getTop();
}
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 347eba0..8a1b957 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -35,7 +35,6 @@
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.EditorInfo;
@@ -43,8 +42,6 @@
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView.OnItemLongClickListener;
import com.android.launcher.R;
import com.android.launcher2.FolderInfo.FolderListener;
@@ -54,9 +51,8 @@
/**
* Represents a set of icons chosen by the user or generated by the system.
*/
-public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener,
- OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget, FolderListener,
- TextView.OnEditorActionListener {
+public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
+ View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener {
protected DragController mDragController;
@@ -102,6 +98,7 @@
private int mFolderNameHeight;
private Rect mHitRect = new Rect();
private Rect mTempRect = new Rect();
+ private boolean mFirstOpen = true;
private boolean mIsEditingName = false;
private InputMethodManager mInputMethodManager;
@@ -135,7 +132,6 @@
if (sHintText == null) {
sHintText = res.getString(R.string.folder_hint_text);
}
- setLayerType(LAYER_TYPE_HARDWARE, null);
}
@Override
@@ -177,15 +173,6 @@
}
};
- public void onItemClick(AdapterView parent, View v, int position, long id) {
- ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
- int[] pos = new int[2];
- v.getLocationOnScreen(pos);
- app.intent.setSourceBounds(new Rect(pos[0], pos[1],
- pos[0] + v.getWidth(), pos[1] + v.getHeight()));
- mLauncher.startActivitySafely(app.intent, app);
- }
-
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
@@ -393,6 +380,12 @@
}
public void animateOpen() {
+ if (mFirstOpen) {
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+ buildLayer();
+ mFirstOpen = false;
+ }
+
positionAndSizeAsIcon();
if (!(getParent() instanceof DragLayer)) return;
@@ -433,14 +426,25 @@
@Override
public void onAnimationEnd(Animator animation) {
mState = STATE_OPEN;
+ setLayerType(LAYER_TYPE_NONE, null);
+ enableHardwareLayersForChildren();
}
});
oa.setDuration(mExpandDuration);
oa.start();
}
+ void enableHardwareLayersForChildren() {
+ ArrayList<View> children = getItemsInReadingOrder();
+ for (View child: children) {
+ child.setLayerType(LAYER_TYPE_HARDWARE, null);
+ }
+ }
+
public void animateClosed() {
if (!(getParent() instanceof DragLayer)) return;
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+ buildLayer();
ObjectAnimator oa;
if (mMode == PARTIAL_GROW) {
@@ -957,4 +961,8 @@
}
return mItemsInReadingOrder;
}
+
+ public void getLocationInDragLayer(int[] loc) {
+ mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
+ }
}
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index 4071433..4978e98 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -55,7 +55,7 @@
private static final int NUM_ITEMS_IN_PREVIEW = 3;
private static final int CONSUMPTION_ANIMATION_DURATION = 100;
private static final int DROP_IN_ANIMATION_DURATION = 400;
- private static final int INITIAL_ITEM_ANIMATION_DURATION = 150;
+ private static final int INITIAL_ITEM_ANIMATION_DURATION = 350;
// The degree to which the inner ring grows when accepting drop
private static final float INNER_RING_GROWTH_FACTOR = 0.15f;
@@ -295,7 +295,7 @@
// This will animate the first item from it's position as an icon into its
// position as the first item in the preview
- animateFirstItem(animateDrawable, DROP_IN_ANIMATION_DURATION);
+ animateFirstItem(animateDrawable, INITIAL_ITEM_ANIMATION_DURATION);
postDelayed(new Runnable() {
public void run() {
@@ -332,7 +332,7 @@
float finalAlpha = index < NUM_ITEMS_IN_PREVIEW ? 0.5f : 0f;
dragLayer.animateView(animateView, from, to, finalAlpha, scale, DROP_IN_ANIMATION_DURATION,
- new DecelerateInterpolator(2), new AccelerateInterpolator(2));
+ new DecelerateInterpolator(2), new AccelerateInterpolator(2), null, false);
postDelayed(new Runnable() {
public void run() {
addItem(item);
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index 5c07cfb..22691a5 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -69,13 +69,15 @@
com.android.internal.R.mipmap.sym_def_app_icon);
}
- public Drawable getFullResIcon(Resources resources, int iconId)
- throws Resources.NotFoundException {
- return resources.getDrawableForDensity(iconId, mIconDpi);
+ public Drawable getFullResIcon(Resources resources, int iconId) {
+ try {
+ return resources.getDrawableForDensity(iconId, mIconDpi);
+ } catch (Resources.NotFoundException e) {
+ return getFullResDefaultActivityIcon();
+ }
}
- public Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager)
- throws Resources.NotFoundException {
+ public Drawable getFullResIcon(ResolveInfo info, PackageManager packageManager) {
Resources resources;
try {
resources = packageManager.getResourcesForApplication(
@@ -178,13 +180,8 @@
entry.title = info.activityInfo.name;
}
- Drawable icon;
- try {
- icon = getFullResIcon(info, mPackageManager);
- } catch (Resources.NotFoundException e) {
- icon = getFullResDefaultActivityIcon();
- }
- entry.icon = Utilities.createIconBitmap(icon, mContext);
+ entry.icon = Utilities.createIconBitmap(
+ getFullResIcon(info, mPackageManager), mContext);
}
return entry;
}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 5c9e4dd..6f64f9d 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -1284,7 +1284,7 @@
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
- // Reset AllApps to it's initial state
+ // Reset AllApps to its initial state
if (mAppsCustomizeContent != null) {
mAppsCustomizeContent.reset();
}
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index 68b1644..db3a4cb 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -24,11 +24,14 @@
import android.database.ContentObserver;
import android.os.Handler;
+import java.lang.ref.WeakReference;
+
public class LauncherApplication extends Application {
public LauncherModel mModel;
public IconCache mIconCache;
private static boolean sIsScreenLarge;
private static float sScreenDensity;
+ WeakReference<LauncherProvider> mLauncherProvider;
@Override
public void onCreate() {
@@ -97,6 +100,14 @@
return mModel;
}
+ void setLauncherProvider(LauncherProvider provider) {
+ mLauncherProvider = new WeakReference<LauncherProvider>(provider);
+ }
+
+ LauncherProvider getLauncherProvider() {
+ return mLauncherProvider.get();
+ }
+
public static boolean isScreenLarge() {
return sIsScreenLarge;
}
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index e8ae9d9..64b38c0 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -88,9 +88,27 @@
private WeakReference<Callbacks> mCallbacks;
- private AllAppsList mAllAppsList; // only access in worker thread
- private IconCache mIconCache;
+ // < only access in worker thread >
+ private AllAppsList mAllAppsList;
+ // sItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by
+ // LauncherModel to their ids
+ static final HashMap<Long, ItemInfo> sItemsIdMap = new HashMap<Long, ItemInfo>();
+
+ // sItems is passed to bindItems, which expects a list of all folders and shortcuts created by
+ // LauncherModel that are directly on the home screen (however, no widgets or shortcuts
+ // within folders).
+ static final ArrayList<ItemInfo> sItems = new ArrayList<ItemInfo>();
+
+ // sAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()
+ static final ArrayList<LauncherAppWidgetInfo> sAppWidgets =
+ new ArrayList<LauncherAppWidgetInfo>();
+
+ // sFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()
+ static final HashMap<Long, FolderInfo> sFolders = new HashMap<Long, FolderInfo>();
+ // </ only access in worker thread >
+
+ private IconCache mIconCache;
private Bitmap mDefaultIcon;
private static int mCellCountX;
@@ -148,9 +166,8 @@
/**
* Move an item in the DB to a new <container, screen, cellX, cellY>
*/
- static void moveItemInDatabase(Context context, ItemInfo item, long container, int screen,
- int cellX, int cellY) {
-
+ static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
+ final int screen, final int cellX, final int cellY) {
item.container = container;
item.screen = screen;
item.cellX = cellX;
@@ -168,6 +185,24 @@
sWorker.post(new Runnable() {
public void run() {
cr.update(uri, values, null, null);
+ ItemInfo modelItem = sItemsIdMap.get(item.id);
+ if (item != modelItem) {
+ // the modelItem needs to match up perfectly with item if our model is to be
+ // consistent with the database-- for now, just require modelItem == item
+ throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
+ "doesn't match original");
+ }
+
+ // Items are added/removed from the corresponding FolderInfo elsewhere, such
+ // as in Workspace.onDrop. Here, we just add/remove them from the list of items
+ // that are on the desktop, as appropriate
+ if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ if (!sItems.contains(modelItem)) {
+ sItems.add(modelItem);
+ }
+ } else {
+ sItems.remove(modelItem);
+ }
}
});
}
@@ -175,8 +210,8 @@
/**
* Resize an item in the DB to a new <spanX, spanY, cellX, cellY>
*/
- static void resizeItemInDatabase(Context context, ItemInfo item, int cellX, int cellY,
- int spanX, int spanY) {
+ static void resizeItemInDatabase(Context context, final ItemInfo item, final int cellX,
+ final int cellY, final int spanX, final int spanY) {
item.spanX = spanX;
item.spanY = spanY;
item.cellX = cellX;
@@ -195,6 +230,13 @@
sWorker.post(new Runnable() {
public void run() {
cr.update(uri, values, null, null);
+ ItemInfo modelItem = sItemsIdMap.get(item.id);
+ if (item != modelItem) {
+ // the modelItem needs to match up perfectly with item if our model is to be
+ // consistent with the database-- for now, just require modelItem == item
+ throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
+ "doesn't match original");
+ }
}
});
}
@@ -316,14 +358,37 @@
final ContentResolver cr = context.getContentResolver();
item.onAddToDatabase(values);
+ Launcher l = (Launcher) context;
+ LauncherApplication app = (LauncherApplication) l.getApplication();
+ item.id = app.getLauncherProvider().generateNewId();
+ values.put(LauncherSettings.Favorites._ID, item.id);
item.updateValuesWithCoordinates(values, cellX, cellY);
- Uri result = cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
- LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
+ sWorker.post(new Runnable() {
+ public void run() {
+ cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
+ LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
- if (result != null) {
- item.id = Integer.parseInt(result.getPathSegments().get(1));
- }
+ sItemsIdMap.put(item.id, item);
+ switch (item.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+ sFolders.put(item.id, (FolderInfo) item);
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ sItems.add(item);
+ }
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ sItems.add(item);
+ }
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ sAppWidgets.add((LauncherAppWidgetInfo) item);
+ break;
+ }
+ }
+ });
}
/**
@@ -355,14 +420,26 @@
/**
* Update an item to the database in a specified container.
*/
- static void updateItemInDatabase(Context context, ItemInfo item) {
+ static void updateItemInDatabase(Context context, final ItemInfo item) {
final ContentValues values = new ContentValues();
final ContentResolver cr = context.getContentResolver();
item.onAddToDatabase(values);
item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
- cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
+ sWorker.post(new Runnable() {
+ public void run() {
+ cr.update(LauncherSettings.Favorites.getContentUri(item.id, false),
+ values, null, null);
+ final ItemInfo modelItem = sItemsIdMap.get(item.id);
+ if (item != modelItem) {
+ // the modelItem needs to match up perfectly with item if our model is to be
+ // consistent with the database-- for now, just require modelItem == item
+ throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
+ "doesn't match original");
+ }
+ }
+ });
}
/**
@@ -370,43 +447,50 @@
* @param context
* @param item
*/
- static void deleteItemFromDatabase(Context context, ItemInfo item) {
+ static void deleteItemFromDatabase(Context context, final ItemInfo item) {
final ContentResolver cr = context.getContentResolver();
final Uri uriToDelete = LauncherSettings.Favorites.getContentUri(item.id, false);
sWorker.post(new Runnable() {
public void run() {
cr.delete(uriToDelete, null, null);
+ switch (item.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+ sFolders.remove(item.id);
+ sItems.remove(item);
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ sItems.remove(item);
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ sAppWidgets.remove((LauncherAppWidgetInfo) item);
+ break;
+ }
+ sItemsIdMap.remove(item.id);
}
});
}
- static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
- deleteFolderContentsFromDatabase(context, info, false);
- }
-
/**
* Remove the contents of the specified folder from the database
*/
- static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info,
- boolean post) {
- // TODO: this post flag is temporary to fix an ordering of commands issue. In future,
- // all db operations will be moved to the worker thread, so this can be discarded at
- // that time.
+ static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
final ContentResolver cr = context.getContentResolver();
- if (!post) {
- cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
- cr.delete(LauncherSettings.Favorites.CONTENT_URI,
- LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
- } else {
- sWorker.post(new Runnable() {
+ sWorker.post(new Runnable() {
public void run() {
cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
+ sItemsIdMap.remove(info.id);
+ sFolders.remove(info.id);
+ sItems.remove(info);
+
cr.delete(LauncherSettings.Favorites.CONTENT_URI,
LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
+ for (ItemInfo childInfo : info.contents) {
+ sItemsIdMap.remove(childInfo.id);
+ }
}
});
- }
}
/**
@@ -547,10 +631,6 @@
private boolean mStopped;
private boolean mLoadAndBindStepFinished;
- final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
- final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
- final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
-
LoaderTask(Context context, boolean isLaunching) {
mContext = context;
mIsLaunching = isLaunching;
@@ -562,14 +642,10 @@
private void loadAndBindWorkspace() {
// Load the workspace
-
- // For now, just always reload the workspace. It's ~100 ms vs. the
- // binding which takes many hundreds of ms.
- // We can reconsider.
if (DEBUG_LOADERS) {
Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
}
- if (true || !mWorkspaceLoaded) {
+ if (!mWorkspaceLoaded) {
loadWorkspace();
if (mStopped) {
return;
@@ -743,9 +819,10 @@
final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
final boolean isSafeMode = manager.isSafeMode();
- mItems.clear();
- mAppWidgets.clear();
- mFolders.clear();
+ sItems.clear();
+ sAppWidgets.clear();
+ sFolders.clear();
+ sItemsIdMap.clear();
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
@@ -834,15 +911,16 @@
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(info);
+ sItems.add(info);
break;
default:
// Item is in a user folder
FolderInfo folderInfo =
- findOrMakeFolder(mFolders, container);
+ findOrMakeFolder(sFolders, container);
folderInfo.add(info);
break;
}
+ sItemsIdMap.put(info.id, info);
// now that we've loaded everthing re-save it with the
// icon in case it disappears somehow.
@@ -861,7 +939,7 @@
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
id = c.getLong(idIndex);
- FolderInfo folderInfo = findOrMakeFolder(mFolders, id);
+ FolderInfo folderInfo = findOrMakeFolder(sFolders, id);
folderInfo.title = c.getString(titleIndex);
folderInfo.id = id;
@@ -877,11 +955,12 @@
}
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(folderInfo);
+ sItems.add(folderInfo);
break;
}
- mFolders.put(folderInfo.id, folderInfo);
+ sItemsIdMap.put(folderInfo.id, folderInfo);
+ sFolders.put(folderInfo.id, folderInfo);
break;
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
@@ -918,8 +997,8 @@
if (!checkItemPlacement(occupied, appWidgetInfo)) {
break;
}
-
- mAppWidgets.add(appWidgetInfo);
+ sItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
+ sAppWidgets.add(appWidgetInfo);
}
break;
}
@@ -993,7 +1072,7 @@
}
});
// Add the items to the workspace.
- N = mItems.size();
+ N = sItems.size();
for (int i=0; i<N; i+=ITEMS_CHUNK) {
final int start = i;
final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
@@ -1001,7 +1080,7 @@
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.bindItems(mItems, start, start+chunkSize);
+ callbacks.bindItems(sItems, start, start+chunkSize);
}
}
});
@@ -1010,7 +1089,7 @@
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.bindFolders(mFolders);
+ callbacks.bindFolders(sFolders);
}
}
});
@@ -1028,10 +1107,10 @@
// is just a hint for the order, and if it's wrong, we'll be okay.
// TODO: instead, we should have that push the current screen into here.
final int currentScreen = oldCallbacks.getCurrentWorkspaceScreen();
- N = mAppWidgets.size();
+ N = sAppWidgets.size();
// once for the current screen
for (int i=0; i<N; i++) {
- final LauncherAppWidgetInfo widget = mAppWidgets.get(i);
+ final LauncherAppWidgetInfo widget = sAppWidgets.get(i);
if (widget.screen == currentScreen) {
mHandler.post(new Runnable() {
public void run() {
@@ -1045,7 +1124,7 @@
}
// once for the other screens
for (int i=0; i<N; i++) {
- final LauncherAppWidgetInfo widget = mAppWidgets.get(i);
+ final LauncherAppWidgetInfo widget = sAppWidgets.get(i);
if (widget.screen != currentScreen) {
mHandler.post(new Runnable() {
public void run() {
@@ -1238,7 +1317,7 @@
Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
- Log.d(TAG, "mItems size=" + mItems.size());
+ Log.d(TAG, "mItems size=" + sItems.size());
}
}
diff --git a/src/com/android/launcher2/LauncherProvider.java b/src/com/android/launcher2/LauncherProvider.java
index a02e449..5ffd984 100644
--- a/src/com/android/launcher2/LauncherProvider.java
+++ b/src/com/android/launcher2/LauncherProvider.java
@@ -32,6 +32,7 @@
import android.content.res.TypedArray;
import android.content.pm.PackageManager;
import android.content.pm.ActivityInfo;
+import android.content.SharedPreferences;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
@@ -80,11 +81,12 @@
static final Uri CONTENT_APPWIDGET_RESET_URI =
Uri.parse("content://" + AUTHORITY + "/appWidgetReset");
- private SQLiteOpenHelper mOpenHelper;
+ private DatabaseHelper mOpenHelper;
@Override
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
+ ((LauncherApplication) getContext()).setLauncherProvider(this);
return true;
}
@@ -113,12 +115,20 @@
return result;
}
+ private static long dbInsertAndCheck(DatabaseHelper helper,
+ SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) {
+ if (!values.containsKey(LauncherSettings.Favorites._ID)) {
+ throw new RuntimeException("Error: attempting to add item without specifying an id");
+ }
+ return db.insert(table, nullColumnHack, values);
+ }
+
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
SqlArguments args = new SqlArguments(uri);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- final long rowId = db.insert(args.table, null, initialValues);
+ final long rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues);
if (rowId <= 0) return null;
uri = ContentUris.withAppendedId(uri, rowId);
@@ -136,7 +146,9 @@
try {
int numValues = values.length;
for (int i = 0; i < numValues; i++) {
- if (db.insert(args.table, null, values[i]) < 0) return 0;
+ if (dbInsertAndCheck(mOpenHelper, db, args.table, null, values[i]) < 0) {
+ return 0;
+ }
}
db.setTransactionSuccessful();
} finally {
@@ -176,6 +188,10 @@
}
}
+ public long generateNewId() {
+ return mOpenHelper.generateNewId();
+ }
+
private static class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG_FAVORITES = "favorites";
private static final String TAG_FAVORITE = "favorite";
@@ -186,11 +202,13 @@
private final Context mContext;
private final AppWidgetHost mAppWidgetHost;
+ private long mMaxId = -1;
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
+ mMaxId = initializeMaxId(getWritableDatabase());
}
/**
@@ -207,7 +225,9 @@
@Override
public void onCreate(SQLiteDatabase db) {
if (LOGD) Log.d(TAG, "creating new launcher database");
-
+
+ mMaxId = 1;
+
db.execSQL("CREATE TABLE favorites (" +
"_id INTEGER PRIMARY KEY," +
"title TEXT," +
@@ -253,7 +273,7 @@
try {
cursor = resolver.query(uri, null, null, null, null);
} catch (Exception e) {
- // Ignore
+ // Ignore
}
// We already have a favorites database in the old provider
@@ -321,7 +341,7 @@
try {
int numValues = rows.length;
for (i = 0; i < numValues; i++) {
- if (db.insert(TABLE_FAVORITES, null, rows[i]) < 0) {
+ if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i]) < 0) {
return 0;
} else {
total++;
@@ -535,7 +555,36 @@
c.close();
}
}
-
+ }
+
+ // Generates a new ID to use for an object 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 generateNewId() {
+ if (mMaxId < 0) {
+ throw new RuntimeException("Error: max id was not initialized");
+ }
+ mMaxId += 1;
+ return mMaxId;
+ }
+
+ private long initializeMaxId(SQLiteDatabase db) {
+ Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null);
+
+ // get the result
+ final int maxIdIndex = 0;
+ long id = -1;
+ if (c != null && c.moveToNext()) {
+ id = c.getLong(maxIdIndex);
+ }
+
+ if (id == -1) {
+ throw new RuntimeException("Error: could not query max id");
+ }
+
+ return id;
}
/**
@@ -712,7 +761,8 @@
values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION);
values.put(Favorites.SPANX, 1);
values.put(Favorites.SPANY, 1);
- db.insert(TABLE_FAVORITES, null, values);
+ values.put(Favorites._ID, generateNewId());
+ dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Unable to add favorite: " + packageName +
"/" + className, e);
@@ -804,7 +854,8 @@
values.put(Favorites.SPANX, spanX);
values.put(Favorites.SPANY, spanY);
values.put(Favorites.APPWIDGET_ID, appWidgetId);
- db.insert(TABLE_FAVORITES, null, values);
+ values.put(Favorites._ID, generateNewId());
+ dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
allocatedAppWidgets = true;
@@ -847,8 +898,8 @@
values.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE);
values.put(Favorites.ICON_PACKAGE, mContext.getPackageName());
values.put(Favorites.ICON_RESOURCE, r.getResourceName(iconResId));
-
- db.insert(TABLE_FAVORITES, null, values);
+ values.put(Favorites._ID, generateNewId());
+ dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
return true;
}
diff --git a/src/com/android/launcher2/SpringLoadedDragController.java b/src/com/android/launcher2/SpringLoadedDragController.java
index 0d4785d..7b4adf3 100644
--- a/src/com/android/launcher2/SpringLoadedDragController.java
+++ b/src/com/android/launcher2/SpringLoadedDragController.java
@@ -39,10 +39,8 @@
// Set a new alarm to expire for the screen that we are hovering over now
public void setAlarm(CellLayout cl) {
- if (mScreen != cl) {
- mAlarm.cancelAlarm();
- mAlarm.setAlarm(ENTER_SPRING_LOAD_HOVER_TIME);
- }
+ mAlarm.cancelAlarm();
+ mAlarm.setAlarm(ENTER_SPRING_LOAD_HOVER_TIME);
mScreen = cl;
}
@@ -52,7 +50,9 @@
// Snap to the screen that we are hovering over now
Workspace w = mLauncher.getWorkspace();
int page = w.indexOfChild(mScreen);
- w.snapToPage(page);
+ if (page != w.getCurrentPage()) {
+ w.snapToPage(page);
+ }
} else {
mLauncher.getDragController().cancelDrag();
}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index caf62b4..fd18338 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -205,8 +205,6 @@
private FolderRingAnimator mDragFolderRingAnimator = null;
private View mLastDragOverView = null;
private boolean mCreateUserFolderOnDrop = false;
- private int mCellWidth = -1;
- private int mCellHeight = -1;
// Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
private float mXDown;
@@ -1284,7 +1282,6 @@
shrink(shrinkState, true);
}
-
// we use this to shrink the workspace for the all apps view and the customize view
public void shrink(ShrinkState shrinkState, boolean animated) {
if (mFirstLayout) {
@@ -2003,9 +2000,9 @@
final int bmpWidth = b.getWidth();
final int bmpHeight = b.getHeight();
- child.getLocationOnScreen(mTempXY);
- final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
- final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
+ mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
+ final int dragLayerX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
+ final int dragLayerY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
Rect dragRect = null;
if (child instanceof BubbleTextView) {
@@ -2021,7 +2018,7 @@
}
mLauncher.lockScreenOrientation();
- mDragController.startDrag(b, screenX, screenY, this, child.getTag(),
+ mDragController.startDrag(b, dragLayerX, dragLayerY, this, child.getTag(),
DragController.DRAG_ACTION_MOVE, dragRect);
b.recycle();
}
@@ -2288,11 +2285,11 @@
}
public void getViewLocationRelativeToSelf(View v, int[] location) {
- getLocationOnScreen(location);
+ getLocationInWindow(location);
int x = location[0];
int y = location[1];
- v.getLocationOnScreen(location);
+ v.getLocationInWindow(location);
int vX = location[0];
int vY = location[1];
@@ -3288,4 +3285,8 @@
return String.format(mContext.getString(R.string.workspace_scroll_format),
page + 1, getChildCount());
}
+
+ public void getLocationInDragLayer(int[] loc) {
+ mLauncher.getDragLayer().getLocationInDragLayer(this, loc);
+ }
}