diff options
author | Adam Cohen <adamcohen@google.com> | 2011-06-01 15:30:43 -0700 |
---|---|---|
committer | Adam Cohen <adamcohen@google.com> | 2011-06-08 15:21:29 -0700 |
commit | c0dcf597084d00e4c23a7fea5fd0738f6c095a6b (patch) | |
tree | 9dcecb4d43b4abc0263d47300536e87a72e33c58 /src/com/android | |
parent | 9578bde6a903925fbda2ecf738c7b00d6fa4026d (diff) | |
download | android_packages_apps_Trebuchet-c0dcf597084d00e4c23a7fea5fd0738f6c095a6b.tar.gz android_packages_apps_Trebuchet-c0dcf597084d00e4c23a7fea5fd0738f6c095a6b.tar.bz2 android_packages_apps_Trebuchet-c0dcf597084d00e4c23a7fea5fd0738f6c095a6b.zip |
Fixing up some Folder bugs
-> Rendering properly while in spring-loaded mode
-> Fixed bug where sometimes the folder's background would vanish
-> Fixed bug where the folder background was "stuck" in a fixed
location, not following the folder
-> Can now add to folders and create folders from spring-loaded mode
Change-Id: Ie1c5583a6230a192e6d07763d001b50053daca43
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/launcher2/AllApps2D.java | 7 | ||||
-rw-r--r-- | src/com/android/launcher2/AllApps3D.java | 30 | ||||
-rw-r--r-- | src/com/android/launcher2/AllAppsPagedView.java | 7 | ||||
-rw-r--r-- | src/com/android/launcher2/ApplicationInfoDropTarget.java | 5 | ||||
-rw-r--r-- | src/com/android/launcher2/AppsCustomizePagedView.java | 17 | ||||
-rw-r--r-- | src/com/android/launcher2/CellLayout.java | 14 | ||||
-rw-r--r-- | src/com/android/launcher2/CustomizePagedView.java | 14 | ||||
-rw-r--r-- | src/com/android/launcher2/DeleteZone.java | 1 | ||||
-rw-r--r-- | src/com/android/launcher2/DragController.java | 10 | ||||
-rw-r--r-- | src/com/android/launcher2/DragSource.java | 4 | ||||
-rw-r--r-- | src/com/android/launcher2/Folder.java | 6 | ||||
-rw-r--r-- | src/com/android/launcher2/FolderIcon.java | 115 | ||||
-rw-r--r-- | src/com/android/launcher2/Launcher.java | 16 | ||||
-rw-r--r-- | src/com/android/launcher2/Workspace.java | 274 |
14 files changed, 310 insertions, 210 deletions
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java index 44af7b7b1..4547f54b3 100644 --- a/src/com/android/launcher2/AllApps2D.java +++ b/src/com/android/launcher2/AllApps2D.java @@ -16,8 +16,6 @@ package com.android.launcher2; -import com.android.launcher.R; - import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -37,6 +35,9 @@ import android.widget.ImageButton; import android.widget.RelativeLayout; import android.widget.TextView; +import com.android.launcher.R; +import com.android.launcher2.DropTarget.DragObject; + import java.util.ArrayList; import java.util.Collections; @@ -208,7 +209,7 @@ public class AllApps2D } @Override - public void onDropCompleted(View target, Object dragInfo, boolean success) { + public void onDropCompleted(View target, DragObject d, boolean success) { } /** diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java index 0e512c6d9..837ddbbab 100644 --- a/src/com/android/launcher2/AllApps3D.java +++ b/src/com/android/launcher2/AllApps3D.java @@ -16,12 +16,6 @@ package com.android.launcher2; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; - -import com.android.launcher.R; - import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -29,9 +23,20 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.PixelFormat; import android.graphics.Rect; -import android.renderscript.*; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.Matrix4f; +import android.renderscript.Mesh; +import android.renderscript.ProgramFragment; +import android.renderscript.ProgramFragmentFixedFunction; +import android.renderscript.ProgramStore; +import android.renderscript.ProgramVertex; +import android.renderscript.ProgramVertexFixedFunction; +import android.renderscript.RSSurfaceView; +import android.renderscript.RenderScript; +import android.renderscript.RenderScriptGL; +import android.renderscript.Sampler; import android.util.AttributeSet; -import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; @@ -42,6 +47,13 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; +import com.android.launcher.R; +import com.android.launcher2.DropTarget.DragObject; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; + public class AllApps3D extends RSSurfaceView implements AllAppsView, View.OnClickListener, View.OnLongClickListener, DragSource { private static final String TAG = "Launcher.AllApps3D"; @@ -744,7 +756,7 @@ public class AllApps3D extends RSSurfaceView } @Override - public void onDropCompleted(View target, Object dragInfo, boolean success) { + public void onDropCompleted(View target, DragObject d, boolean success) { mLauncher.getWorkspace().onDragStopped(success); mLauncher.unlockScreenOrientation(); } diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java index 0f364f865..ae8b970fb 100644 --- a/src/com/android/launcher2/AllAppsPagedView.java +++ b/src/com/android/launcher2/AllAppsPagedView.java @@ -16,9 +16,6 @@ package com.android.launcher2; -import com.android.launcher.R; -import com.android.launcher2.DropTarget.DragObject; - import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -34,6 +31,8 @@ import android.view.animation.AnimationUtils; import android.widget.Checkable; import android.widget.TextView; +import com.android.launcher.R; + import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -412,7 +411,7 @@ public class AllAppsPagedView extends PagedViewWithDraggableItems implements All } @Override - public void onDropCompleted(View target, Object dragInfo, boolean success) { + public void onDropCompleted(View target, DragObject d, boolean success) { // close the choice action mode if we have a proper drop if (target != this) { endChoiceMode(); diff --git a/src/com/android/launcher2/ApplicationInfoDropTarget.java b/src/com/android/launcher2/ApplicationInfoDropTarget.java index 311ac7e21..fa4663acf 100644 --- a/src/com/android/launcher2/ApplicationInfoDropTarget.java +++ b/src/com/android/launcher2/ApplicationInfoDropTarget.java @@ -16,9 +16,6 @@ package com.android.launcher2; -import com.android.launcher.R; -import com.android.launcher2.DropTarget.DragObject; - import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; @@ -30,6 +27,8 @@ import android.graphics.PorterDuffColorFilter; import android.util.AttributeSet; import android.view.View; +import com.android.launcher.R; + /** * Implements a DropTarget which allows applications to be dropped on it, * in order to launch the application info for that app. diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java index 7c6742f31..62a8936a1 100644 --- a/src/com/android/launcher2/AppsCustomizePagedView.java +++ b/src/com/android/launcher2/AppsCustomizePagedView.java @@ -16,11 +16,6 @@ package com.android.launcher2; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -38,9 +33,9 @@ import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Rect; +import android.graphics.Bitmap.Config; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; @@ -56,6 +51,12 @@ import android.widget.TextView; import android.widget.Toast; import com.android.launcher.R; +import com.android.launcher2.DropTarget.DragObject; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements AllAppsView, View.OnClickListener, DragSource { @@ -448,7 +449,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen @Override public void onDragViewVisible() {} @Override - public void onDropCompleted(View target, Object dragInfo, boolean success) { + public void onDropCompleted(View target, DragObject d, boolean success) { endDragging(success); // Display an error message if the drag failed due to there not being enough space on the @@ -459,7 +460,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen int currentScreen = mLauncher.getCurrentWorkspaceScreen(); Workspace workspace = (Workspace) target; CellLayout layout = (CellLayout) workspace.getChildAt(currentScreen); - ItemInfo itemInfo = (ItemInfo) dragInfo; + ItemInfo itemInfo = (ItemInfo) d.dragInfo; if (layout != null) { layout.calculateSpans(itemInfo); showOutOfSpaceMessage = diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index eb92d2039..12b0158be 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -16,8 +16,6 @@ package com.android.launcher2; -import java.util.Arrays; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -49,6 +47,8 @@ import android.view.animation.LayoutAnimationController; import com.android.launcher.R; +import java.util.Arrays; + public class CellLayout extends ViewGroup { static final String TAG = "CellLayout"; @@ -1150,12 +1150,12 @@ public class CellLayout extends ViewGroup { // re-mark space taken by ignoreView as occupied markCellsAsOccupiedForView(ignoreView); - // Return null if no suitable location found - if (bestDistance < Double.MAX_VALUE) { - return bestXY; - } else { - return null; + // Return -1, -1 if no suitable location found + if (bestDistance == Double.MAX_VALUE) { + bestXY[0] = -1; + bestXY[1] = -1; } + return bestXY; } /** diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java index 932af8915..b2a7603b5 100644 --- a/src/com/android/launcher2/CustomizePagedView.java +++ b/src/com/android/launcher2/CustomizePagedView.java @@ -16,10 +16,6 @@ package com.android.launcher2; -import com.android.launcher.R; - -import org.xmlpull.v1.XmlPullParser; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; @@ -54,7 +50,6 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.View.MeasureSpec; import android.view.animation.DecelerateInterpolator; import android.view.animation.LinearInterpolator; import android.widget.Checkable; @@ -62,6 +57,11 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import com.android.launcher.R; +import com.android.launcher2.DropTarget.DragObject; + +import org.xmlpull.v1.XmlPullParser; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -402,7 +402,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems } } - public void onDropCompleted(View target, Object dragInfo, boolean success) { + public void onDropCompleted(View target, DragObject d, boolean success) { final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer); // Create a view, identical to the drag view, that is only used for animating the @@ -413,7 +413,7 @@ public class CustomizePagedView extends PagedViewWithDraggableItems if (success) { resetCheckedItem(true); - animateDropOntoScreen(animView, (ItemInfo) dragInfo, DROP_ANIM_DURATION, 0); + animateDropOntoScreen(animView, (ItemInfo) d.dragInfo, DROP_ANIM_DURATION, 0); } else { // Animate the icon/widget back to its original position animateIntoPosition(animView, mDragViewOrigin[0], mDragViewOrigin[1], new Runnable() { diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java index c349e5d72..025b292ff 100644 --- a/src/com/android/launcher2/DeleteZone.java +++ b/src/com/android/launcher2/DeleteZone.java @@ -33,7 +33,6 @@ import android.view.View; import android.view.animation.AccelerateInterpolator; import com.android.launcher.R; -import com.android.launcher2.DropTarget.DragObject; public class DeleteZone extends IconDropTarget { private static final int ORIENTATION_HORIZONTAL = 1; diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java index 1690cac71..8ad5c7ce5 100644 --- a/src/com/android/launcher2/DragController.java +++ b/src/com/android/launcher2/DragController.java @@ -16,8 +16,6 @@ package com.android.launcher2; -import java.util.ArrayList; - import android.content.Context; import android.graphics.Bitmap; import android.graphics.Rect; @@ -35,7 +33,8 @@ import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import com.android.launcher.R; -import com.android.launcher2.DropTarget.DragObject; + +import java.util.ArrayList; /** * Class for initiating a drag within a view or across multiple views. @@ -374,7 +373,7 @@ public class DragController { public void cancelDrag() { if (mDragging) { // Should we also be calling onDragExit() here? - mDragObject.dragSource.onDropCompleted(null, mDragObject.dragInfo, false); + mDragObject.dragSource.onDropCompleted(null, mDragObject, false); } endDrag(); } @@ -572,8 +571,7 @@ public class DragController { accepted = true; } } - mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject.dragInfo, accepted); - + mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, accepted); } private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) { diff --git a/src/com/android/launcher2/DragSource.java b/src/com/android/launcher2/DragSource.java index 649120d21..2a8f263a5 100644 --- a/src/com/android/launcher2/DragSource.java +++ b/src/com/android/launcher2/DragSource.java @@ -18,6 +18,8 @@ package com.android.launcher2; import android.view.View; +import com.android.launcher2.DropTarget.DragObject; + /** * Interface defining an object that can originate a drag. * @@ -29,5 +31,5 @@ public interface DragSource { */ void onDragViewVisible(); - void onDropCompleted(View target, Object dragInfo, boolean success); + void onDropCompleted(View target, DragObject d, boolean success); } diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java index 0b35acbb1..08907c99a 100644 --- a/src/com/android/launcher2/Folder.java +++ b/src/com/android/launcher2/Folder.java @@ -16,8 +16,6 @@ package com.android.launcher2; -import java.util.ArrayList; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; @@ -43,6 +41,8 @@ import android.widget.AdapterView.OnItemLongClickListener; import com.android.launcher.R; import com.android.launcher2.FolderInfo.FolderListener; +import java.util.ArrayList; + /** * Represents a set of icons chosen by the user or generated by the system. */ @@ -448,7 +448,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL return r; } - public void onDropCompleted(View target, Object dragInfo, boolean success) { + public void onDropCompleted(View target, DragObject d, boolean success) { } public boolean isDropEnabled() { diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java index 952d704be..449068c56 100644 --- a/src/com/android/launcher2/FolderIcon.java +++ b/src/com/android/launcher2/FolderIcon.java @@ -16,8 +16,6 @@ package com.android.launcher2; -import java.util.ArrayList; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; @@ -36,12 +34,15 @@ import android.widget.FrameLayout; import android.widget.TextView; import com.android.launcher.R; +import com.android.launcher2.DropTarget.DragObject; import com.android.launcher2.FolderInfo.FolderListener; +import java.util.ArrayList; + /** * An icon that can appear on in the workspace representing an {@link UserFolder}. */ -public class FolderIcon extends FrameLayout implements DropTarget, FolderListener { +public class FolderIcon extends FrameLayout implements FolderListener { private Launcher mLauncher; Folder mFolder; FolderInfo mInfo; @@ -63,7 +64,7 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene private static final float OUTER_RING_GROWTH_FACTOR = 0.3f; // The amount of vertical spread between items in the stack [0...1] - private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f; + private static final float PERSPECTIVE_SHIFT_FACTOR = 0.3f; // The degree to which the item in the back of the stack is scaled [0...1] // (0 means it's not scaled at all, 1 means it's scaled to nothing) @@ -72,9 +73,6 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene // The percentage of the FolderIcons view that will be dedicated to the items preview private static final float SPACE_PERCENTAGE_FOR_ICONS = 0.8f; - public static Drawable sFolderOuterRingDrawable = null; - public static Drawable sFolderInnerRingDrawable = null; - private int mOriginalWidth = -1; private int mOriginalHeight = -1; @@ -127,29 +125,43 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene public float mInnerRingScale; public FolderIcon mFolderIcon = null; private Launcher mLauncher; + public Drawable mOuterRingDrawable = null; + public Drawable mInnerRingDrawable = null; + public static Drawable sSharedOuterRingDrawable = null; + public static Drawable sSharedInnerRingDrawable = null; + private ValueAnimator mAcceptAnimator; + private ValueAnimator mNeutralAnimator; public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) { mLauncher = launcher; mFolderIcon = folderIcon; - if (sFolderOuterRingDrawable == null) { - sFolderOuterRingDrawable = + mOuterRingDrawable = + launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo); + mInnerRingDrawable = + launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo); + if (sSharedOuterRingDrawable == null) { + sSharedOuterRingDrawable = launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo); } - if (sFolderInnerRingDrawable == null) { - sFolderInnerRingDrawable = + if (sSharedInnerRingDrawable == null) { + sSharedInnerRingDrawable = launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo); } } + // Location is expressed in window coordinates public void setLocation(int x, int y) { mFolderLocX = x; mFolderLocY = y; } public void animateToAcceptState() { - ValueAnimator va = ValueAnimator.ofFloat(0f, 1f); - va.setDuration(CONSUMPTION_ANIMATION_DURATION); - va.addUpdateListener(new AnimatorUpdateListener() { + if (mNeutralAnimator != null) { + mNeutralAnimator.cancel(); + } + mAcceptAnimator = ValueAnimator.ofFloat(0f, 1f); + mAcceptAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION); + mAcceptAnimator.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { final float percent = (Float) animation.getAnimatedValue(); mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR; @@ -160,25 +172,24 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene } } }); - va.addListener(new AnimatorListenerAdapter() { + mAcceptAnimator.addListener(new AnimatorListenerAdapter() { @Override - public void onAnimationEnd(Animator animation) { - // Instead of setting the background drawable to null, we set the color to - // transparent. Setting the background drawable to null results in onDraw - // not getting called. + public void onAnimationStart(Animator animation) { if (mFolderIcon != null) { - mFolderIcon.setBackgroundColor(Color.TRANSPARENT); - mFolderIcon.requestLayout(); + mFolderIcon.setBackgroundDrawable(null); } } }); - va.start(); + mAcceptAnimator.start(); } public void animateToNaturalState() { - ValueAnimator va = ValueAnimator.ofFloat(0f, 1f); - va.setDuration(CONSUMPTION_ANIMATION_DURATION); - va.addUpdateListener(new AnimatorUpdateListener() { + if (mAcceptAnimator != null) { + mAcceptAnimator.cancel(); + } + mNeutralAnimator = ValueAnimator.ofFloat(0f, 1f); + mNeutralAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION); + mNeutralAnimator.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { final float percent = (Float) animation.getAnimatedValue(); mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR @@ -191,18 +202,19 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene } } }); - va.addListener(new AnimatorListenerAdapter() { + mNeutralAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (mFolderIcon != null) { - mFolderIcon.setBackgroundDrawable(sFolderInnerRingDrawable); + mFolderIcon.setBackgroundDrawable(mInnerRingDrawable); } mLauncher.getWorkspace().hideFolderAccept(FolderRingAnimator.this); } }); - va.start(); + mNeutralAnimator.start(); } + // Location is expressed in window coordinates public void getLocation(int[] loc) { loc[0] = mFolderLocX; loc[1] = mFolderLocY; @@ -224,8 +236,8 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene !mFolder.isFull() && item != mInfo); } - public boolean acceptDrop(DragObject d) { - final ItemInfo item = (ItemInfo) d.dragInfo; + public boolean acceptDrop(Object dragInfo) { + final ItemInfo item = (ItemInfo) dragInfo; return willAcceptItem(item); } @@ -234,19 +246,6 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene LauncherModel.addOrMoveItemInDatabase(mLauncher, item, mInfo.id, 0, item.cellX, item.cellY); } - public void onDrop(DragObject d) { - ShortcutInfo item; - if (d.dragInfo instanceof ApplicationInfo) { - // Came from all apps -- make a copy - item = ((ApplicationInfo) d.dragInfo).makeShortcut(); - } else { - item = (ShortcutInfo) d.dragInfo; - } - item.cellX = -1; - item.cellY = -1; - addItem(item); - } - void saveState(CellLayout.LayoutParams lp) { mOriginalWidth = lp.width; mOriginalHeight = lp.height; @@ -255,35 +254,48 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene private void determineFolderLocationInWorkspace() { int tvLocation[] = new int[2]; int wsLocation[] = new int[2]; - getLocationOnScreen(tvLocation); - mLauncher.getWorkspace().getLocationOnScreen(wsLocation); + getLocationInWindow(tvLocation); + mLauncher.getWorkspace().getLocationInWindow(wsLocation); int x = tvLocation[0] - wsLocation[0] + getMeasuredWidth() / 2; int y = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2; mFolderRingAnimator.setLocation(x, y); } - public void onDragEnter(DragObject d) { - if (!willAcceptItem((ItemInfo) d.dragInfo)) return; + public void onDragEnter(Object dragInfo) { + if (!willAcceptItem((ItemInfo) dragInfo)) return; determineFolderLocationInWorkspace(); mLauncher.getWorkspace().showFolderAccept(mFolderRingAnimator); mFolderRingAnimator.animateToAcceptState(); } - public void onDragOver(DragObject d) { + public void onDragOver(Object dragInfo) { } - public void onDragExit(DragObject d) { - if (!willAcceptItem((ItemInfo) d.dragInfo)) return; + public void onDragExit(Object dragInfo) { + if (!willAcceptItem((ItemInfo) dragInfo)) return; mFolderRingAnimator.animateToNaturalState(); } + public void onDrop(Object dragInfo) { + ShortcutInfo item; + if (dragInfo instanceof ApplicationInfo) { + // Came from all apps -- make a copy + item = ((ApplicationInfo) dragInfo).makeShortcut(); + } else { + item = (ShortcutInfo) dragInfo; + } + item.cellX = -1; + item.cellY = -1; + addItem(item); + } + public DropTarget getDropTargetDelegate(DragObject d) { return null; } @Override - protected void onDraw(Canvas canvas) { + protected void dispatchDraw(Canvas canvas) { if (mFolder == null) return; if (mFolder.getItemCount() == 0) return; @@ -337,7 +349,6 @@ public class FolderIcon extends FrameLayout implements DropTarget, FolderListene } canvas.restore(); } - canvas.restore(); } diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index eb533fe60..22ce003f4 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -17,14 +17,6 @@ package com.android.launcher2; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -107,6 +99,14 @@ import com.android.common.Search; import com.android.launcher.R; import com.android.launcher2.Workspace.ShrinkState; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + /** * Default launcher application. */ diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index e0472fc0d..812763f86 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -16,10 +16,6 @@ package com.android.launcher2; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -69,6 +65,10 @@ import com.android.launcher.R; import com.android.launcher2.FolderIcon.FolderRingAnimator; import com.android.launcher2.InstallWidgetReceiver.WidgetMimeTypeHandlerData; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + /** * The workspace is a wide area with a wallpaper and a finite number of pages. * Each page contains a number of icons, folders or widgets the user can @@ -136,7 +136,7 @@ public class Workspace extends SmoothPagedView /** * Target drop area calculated during last acceptDrop call. */ - private int[] mTargetCell = null; + private int[] mTargetCell = new int[2]; /** * The CellLayout that is currently being dragged over @@ -156,6 +156,7 @@ public class Workspace extends SmoothPagedView private float[] mTempTouchCoordinates = new float[2]; private float[] mTempCellLayoutCenterCoordinates = new float[2]; private float[] mTempDragBottomRightCoordinates = new float[2]; + private float[] mTempFloatTuple = new float[2]; private Matrix mTempInverseMatrix = new Matrix(); private int[] mTempLocation = new int[2]; @@ -222,7 +223,7 @@ public class Workspace extends SmoothPagedView private ArrayList<FolderRingAnimator> mFolderOuterRings = new ArrayList<FolderRingAnimator>(); // Variables relating to the creation of user folders by hovering shortcuts over shortcuts - private static final int FOLDER_CREATION_TIMEOUT = 400; + private static final int FOLDER_CREATION_TIMEOUT = 250; private final Alarm mFolderCreationAlarm = new Alarm(); private FolderRingAnimator mDragFolderRingAnimator = null; private View mLastDragOverView = null; @@ -1232,29 +1233,63 @@ public class Workspace extends SmoothPagedView // The folder outer / inner ring image(s) for (int i = 0; i < mFolderOuterRings.size(); i++) { + View currentPage = getChildAt(getCurrentPage()); + Matrix m = currentPage.getMatrix(); // Draw outer ring FolderRingAnimator fra = mFolderOuterRings.get(i); - Drawable d = FolderIcon.sFolderOuterRingDrawable; + Drawable d = FolderRingAnimator.sSharedOuterRingDrawable; int width = (int) (d.getIntrinsicWidth() * fra.getOuterRingScale()); int height = (int) (d.getIntrinsicHeight() * fra.getOuterRingScale()); fra.getLocation(mTempLocation); - int x = mTempLocation[0] + mScrollX - width / 2; - int y = mTempLocation[1] + mScrollY - height / 2; - d.setBounds(x, y, x + width, y + height); + + // First we map the folder's location from window coordinates to its containing + // CellLayout's coordinates. Then we transform the coordinates according to the + // CellLayout's transform. Finally, we map this back into the coordinates of the + // the window (ie. Workspace). + int x = mTempLocation[0] + mScrollX - width / 2 - currentPage.getLeft(); + int y = mTempLocation[1] + mScrollY - height / 2 - currentPage.getTop(); + mTempFloatTuple[0] = x; + mTempFloatTuple[1] = y; + m.mapPoints(mTempFloatTuple); + x = (int) (mTempFloatTuple[0]) + currentPage.getLeft(); + y = (int) (mTempFloatTuple[1]) + currentPage.getTop(); + + canvas.save(); + canvas.translate(x, y); + d.setBounds(0, 0, (int) (width * currentPage.getScaleX()), + (int) (height * currentPage.getScaleY())); d.draw(canvas); + canvas.restore(); // Draw inner ring if (fra.mFolderIcon != null) { - int folderWidth = fra.mFolderIcon != null ? fra.mFolderIcon.getMeasuredWidth() : mCellWidth; - int folderHeight = fra.mFolderIcon != null ? fra.mFolderIcon.getMeasuredWidth() : mCellHeight; - d = FolderIcon.sFolderInnerRingDrawable; + int folderWidth = fra.mFolderIcon != null ? + fra.mFolderIcon.getMeasuredWidth() : mCellWidth; + int folderHeight = fra.mFolderIcon != null ? + fra.mFolderIcon.getMeasuredWidth() : mCellHeight; + d = FolderRingAnimator.sSharedInnerRingDrawable; width = (int) (folderWidth * fra.getInnerRingScale()); height = (int) (folderHeight * fra.getInnerRingScale()); - x = mTempLocation[0] + mScrollX - width / 2; - y = mTempLocation[1] + mScrollY - height / 2; - d.setBounds(x, y, x + width, y + height); + + // First we map the folder's location from window coordinates to its containing + // CellLayout's coordinates. Then we transform the coordinates according to the + // CellLayout's transform. Finally, we map this back into the coordinates of the + // the window (ie. Workspace). + x = mTempLocation[0] + mScrollX - width / 2 - currentPage.getLeft(); + y = mTempLocation[1] + mScrollY - height / 2 - currentPage.getTop(); + mTempFloatTuple[0] = x; + mTempFloatTuple[1] = y; + m.mapPoints(mTempFloatTuple); + x = (int) (mTempFloatTuple[0]) + currentPage.getLeft(); + y = (int) (mTempFloatTuple[1]) + currentPage.getTop(); + + canvas.save(); + canvas.translate(x, y); + d.setBounds(0, 0, (int) (width * currentPage.getScaleX()), + (int) (height * currentPage.getScaleY())); d.draw(canvas); + canvas.restore(); } } super.onDraw(canvas); @@ -1867,7 +1902,7 @@ public class Workspace extends SmoothPagedView mLastDragView = null; // In the success case, DragController has already called onDragExit() if (!success) { - doDragExit(); + doDragExit(null); } mIsDragInProcess = false; updateWhichPagesAcceptDrops(mShrinkState); @@ -2407,42 +2442,29 @@ public class Workspace extends SmoothPagedView return true; } - boolean willCreateUserFolder(ItemInfo info, CellLayout target, int originX, int originY) { - mTargetCell = findNearestArea(originX, originY, 1, 1, target, mTargetCell); - - View v = target.getChildAt(mTargetCell[0], mTargetCell[1]); - boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] && - mDragInfo.cellY == mTargetCell[1]); + boolean willCreateUserFolder(ItemInfo info, View v, int[] targetCell) { + boolean hasntMoved = mDragInfo != null + && (mDragInfo.cellX == targetCell[0] && mDragInfo.cellY == targetCell[1]); if (v == null || hasntMoved) return false; boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo); boolean willBecomeShortcut = - (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || - info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT); + (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || + info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT); return (aboveShortcut && willBecomeShortcut); } - boolean createUserFolderIfNecessary(View newView, CellLayout target, int originX, - int originY, boolean external) { - int spanX = mDragInfo != null ? mDragInfo.spanX : 1; - int spanY = mDragInfo != null ? mDragInfo.spanY : 1; - - // First we find the cell nearest to point at which the item is dropped, without - // any consideration to whether there is an item there. - mTargetCell = findNearestArea(originX, originY, - spanX, spanY, target, - mTargetCell); - - View v = target.getChildAt(mTargetCell[0], mTargetCell[1]); - boolean hasntMoved = mDragInfo != null && (mDragInfo.cellX == mTargetCell[0] && - mDragInfo.cellY == mTargetCell[1]); + boolean createUserFolderIfNecessary(View newView, CellLayout target, + int[] targetCell, boolean external) { + View v = target.getChildAt(targetCell[0], targetCell[1]); + boolean hasntMoved = mDragInfo != null + && (mDragInfo.cellX == targetCell[0] && mDragInfo.cellY == targetCell[1]); if (v == null || hasntMoved || !mCreateUserFolderOnDrop) return false; mCreateUserFolderOnDrop = false; - final int screen = (mTargetCell == null) ? - mDragInfo.screen : indexOfChild(target); + final int screen = (targetCell == null) ? mDragInfo.screen : indexOfChild(target); boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo); boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo); @@ -2458,7 +2480,7 @@ public class Workspace extends SmoothPagedView } target.removeView(v); - FolderIcon fi = mLauncher.addFolder(screen, mTargetCell[0], mTargetCell[1]); + FolderIcon fi = mLauncher.addFolder(screen, targetCell[0], targetCell[1]); destInfo.cellX = -1; destInfo.cellY = -1; sourceInfo.cellX = -1; @@ -2470,6 +2492,26 @@ public class Workspace extends SmoothPagedView return false; } + boolean addToExistingFolderIfNecessary(View newView, CellLayout target, int[] tagetCell, + Object dragInfo, boolean external) { + View dropOverView = target.getChildAt(tagetCell[0], tagetCell[1]); + if (dropOverView instanceof FolderIcon) { + FolderIcon fi = (FolderIcon) dropOverView; + if (fi.acceptDrop(dragInfo)) { + fi.onDrop(dragInfo); + + // if the drag started here, we need to remove it from the workspace + if (!external) { + int fromScreen = mDragInfo.screen; + CellLayout sourceLayout = (CellLayout) getChildAt(fromScreen); + sourceLayout.removeView(newView); + } + return true; + } + } + return false; + } + public void onDrop(DragObject d) { mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView, @@ -2518,13 +2560,25 @@ public class Workspace extends SmoothPagedView if (dropTargetLayout != null) { // Move internally - final int screen = (mTargetCell == null) ? + final int screen = (mTargetCell[0] < 0) ? mDragInfo.screen : indexOfChild(dropTargetLayout); - // If the item being dropped is a shortcut and the nearest drop cell also contains + int spanX = mDragInfo != null ? mDragInfo.spanX : 1; + int spanY = mDragInfo != null ? mDragInfo.spanY : 1; + // First we find the cell nearest to point at which the item is + // dropped, without any consideration to whether there is an item there. + mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], (int) + mDragViewVisualCenter[1], spanX, spanY, dropTargetLayout, mTargetCell); + // If the item being dropped is a shortcut and the nearest drop + // cell also contains // a shortcut, then create a folder with the two shortcuts. if (!dropInscrollArea && createUserFolderIfNecessary(cell, dropTargetLayout, - (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], false)) { + mTargetCell, false)) { + return; + } + + if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell, + d.dragInfo, false)) { return; } @@ -2538,12 +2592,12 @@ public class Workspace extends SmoothPagedView snapToPage(screen); } - if (mTargetCell != null) { + if (mTargetCell[0] >= 0 && mTargetCell[1] >= 0) { if (screen != mDragInfo.screen) { // Reparent the view ((CellLayout) getChildAt(mDragInfo.screen)).removeView(cell); - addInScreen(cell, screen, mTargetCell[0], mTargetCell[1], - mDragInfo.spanX, mDragInfo.spanY); + addInScreen(cell, screen, mTargetCell[0], mTargetCell[1], mDragInfo.spanX, + mDragInfo.spanY); } // update the item's position after drop @@ -2565,10 +2619,9 @@ public class Workspace extends SmoothPagedView if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) { final Runnable resizeRunnable = new Runnable() { public void run() { - DragLayer dragLayer = (DragLayer) - mLauncher.findViewById(R.id.drag_layer); - dragLayer.addResizeFrame(info, hostView, - cellLayout); + DragLayer dragLayer = + (DragLayer) mLauncher.findViewById(R.id.drag_layer); + dragLayer.addResizeFrame(info, hostView, cellLayout); } }; post(new Runnable() { @@ -2617,7 +2670,7 @@ public class Workspace extends SmoothPagedView public void onDragEnter(DragObject d) { mDragTargetLayout = null; // Reset the drag state - + mLastDragOverView = null; if (!mIsSmall) { mDragTargetLayout = getCurrentDropLayout(); mDragTargetLayout.onDragEnter(); @@ -3036,8 +3089,8 @@ public class Workspace extends SmoothPagedView if (widgetInfo.spanX == -1) { // Calculate the grid spans needed to fit this widget - int[] spans = layout.rectToCell( - widgetInfo.minWidth, widgetInfo.minHeight, null); + int[] spans = layout.rectToCell(widgetInfo.minWidth, + widgetInfo.minHeight, null); item.spanX = spans[0]; item.spanY = spans[1]; } @@ -3049,37 +3102,40 @@ public class Workspace extends SmoothPagedView mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null); ItemInfo info = (ItemInfo) d.dragInfo; - boolean willCreateUserFolder = willCreateUserFolder(info, mDragTargetLayout, - (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1]); + mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], + (int) mDragViewVisualCenter[1], 1, 1, mDragTargetLayout, mTargetCell); + final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], + mTargetCell[1]); - View newDropOver = null; - if (willCreateUserFolder) { - newDropOver = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]); - } + boolean userFolderPending = willCreateUserFolder(info, dragOverView, + mTargetCell); + boolean isOverFolder = dragOverView instanceof FolderIcon; + if (dragOverView != mLastDragOverView) { + cancelFolderCreation(); + if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) { - if (newDropOver != mLastDragOverView || !willCreateUserFolder) { - if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) { - mDragFolderRingAnimator.animateToNaturalState(); + ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo); } - mCreateUserFolderOnDrop = false; - mFolderCreationAlarm.cancelAlarm(); - mIsDraggingOverIcon = false; } - if (willCreateUserFolder && !mIsDraggingOverIcon) { - mIsDraggingOverIcon = true; - - mLastDragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]); - mFolderCreationAlarm.setOnAlarmListener(new FolderCreationAlarmListener(mLastDragOverView)); + if (userFolderPending && dragOverView != mLastDragOverView) { + mFolderCreationAlarm.setOnAlarmListener(new + FolderCreationAlarmListener(dragOverView)); mFolderCreationAlarm.setAlarm(FOLDER_CREATION_TIMEOUT); + } + + if (dragOverView != mLastDragOverView && isOverFolder) { - mDragTargetLayout.clearDragOutlines(); + ((FolderIcon) dragOverView).onDragEnter(d.dragInfo); + if (mDragTargetLayout != null) { + mDragTargetLayout.clearDragOutlines(); + } } + mLastDragOverView = dragOverView; - if (!mCreateUserFolderOnDrop) { + if (!mCreateUserFolderOnDrop && !isOverFolder) { mDragTargetLayout.visualizeDropLocation(child, mDragOutline, - (int) mDragViewVisualCenter[0], - (int) mDragViewVisualCenter[1], + (int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1], item.spanX, item.spanY); } } @@ -3087,6 +3143,14 @@ public class Workspace extends SmoothPagedView } } + private void cancelFolderCreation() { + if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) { + mDragFolderRingAnimator.animateToNaturalState(); + } + mCreateUserFolderOnDrop = false; + mFolderCreationAlarm.cancelAlarm(); + } + class FolderCreationAlarmListener implements OnAlarmListener { View v; @@ -3097,15 +3161,15 @@ public class Workspace extends SmoothPagedView public void onAlarm(Alarm alarm) { int tvLocation[] = new int[2]; int wsLocation[] = new int[2]; - v.getLocationOnScreen(tvLocation); - getLocationOnScreen(wsLocation); + v.getLocationInWindow(tvLocation); + getLocationInWindow(wsLocation); - if (mCellWidth < 0 || mCellHeight < 0) { + if (mCellWidth < 0 || mCellHeight < 0 && mDragTargetLayout != null) { mCellWidth = mDragTargetLayout.getCellWidth(); mCellHeight = mDragTargetLayout.getCellHeight(); } - int x = tvLocation[0] - wsLocation[0] + mCellWidth / 2; - int y = tvLocation[1] - wsLocation[1] + mCellHeight / 2; + int x = tvLocation[0] - wsLocation[0] + v.getMeasuredWidth() / 2; + int y = tvLocation[1] - wsLocation[1] + v.getMeasuredHeight() / 2; if (mDragFolderRingAnimator == null) { mDragFolderRingAnimator = new FolderRingAnimator(mLauncher, null); @@ -3114,16 +3178,22 @@ public class Workspace extends SmoothPagedView mDragFolderRingAnimator.animateToAcceptState(); showFolderAccept(mDragFolderRingAnimator); mCreateUserFolderOnDrop = true; - mDragTargetLayout.clearDragOutlines(); + if (mDragTargetLayout != null) { + mDragTargetLayout.clearDragOutlines(); + } } } - private void doDragExit() { + private void doDragExit(DragObject d) { mWasSpringLoadedOnDragExit = mShrinkState == ShrinkState.SPRING_LOADED; - if (mDragFolderRingAnimator != null && mCreateUserFolderOnDrop) { mDragFolderRingAnimator.animateToNaturalState(); } + if (mLastDragOverView != null && mLastDragOverView instanceof FolderIcon) { + if (d != null) { + ((FolderIcon) mLastDragOverView).onDragExit(d.dragInfo); + } + } mFolderCreationAlarm.cancelAlarm(); if (mDragTargetLayout != null) { @@ -3139,7 +3209,7 @@ public class Workspace extends SmoothPagedView } public void onDragExit(DragObject d) { - doDragExit(); + doDragExit(d); } @Override @@ -3210,25 +3280,32 @@ public class Workspace extends SmoothPagedView (ShortcutInfo) info); break; case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: - view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, - cellLayout, (FolderInfo) info, mIconCache); + view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout, + (FolderInfo) info, mIconCache); break; default: throw new IllegalStateException("Unknown item type: " + info.itemType); } - // If the item being dropped is a shortcut and the nearest drop cell also contains - // a shortcut, then create a folder with the two shortcuts. - if (touchXY != null && createUserFolderIfNecessary(view, cellLayout, touchXY[0], - touchXY[1], true)) { - return; + int spanX = mDragInfo != null ? mDragInfo.spanX : 1; + int spanY = mDragInfo != null ? mDragInfo.spanY : 1; + // First we find the cell nearest to point at which the item is + // dropped, without any consideration to whether there is an item there. + if (touchXY != null) { + mTargetCell = findNearestArea((int) touchXY[0], (int) touchXY[1], spanX, spanY, + cellLayout, mTargetCell); + if (createUserFolderIfNecessary(view, cellLayout, mTargetCell, true)) { + return; + } + if (addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, dragInfo, true)) { + return; + } } - mTargetCell = new int[2]; if (touchXY != null) { // when dragging and dropping, just find the closest free spot - mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, null, cellLayout, - mTargetCell); + mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], 1, 1, null, + cellLayout, mTargetCell); } else { cellLayout.findCellForSpan(mTargetCell, 1, 1); } @@ -3309,13 +3386,13 @@ public class Workspace extends SmoothPagedView /** * Called at the end of a drag which originated on the workspace. */ - public void onDropCompleted(View target, Object dragInfo, boolean success) { + public void onDropCompleted(View target, DragObject d, boolean success) { if (success) { if (target != this && mDragInfo != null) { final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen); cellLayout.removeView(mDragInfo.cell); if (mDragInfo.cell instanceof DropTarget) { - mDragController.removeDropTarget((DropTarget)mDragInfo.cell); + mDragController.removeDropTarget((DropTarget) mDragInfo.cell); } // final Object tag = mDragInfo.cell.getTag(); } @@ -3323,7 +3400,7 @@ public class Workspace extends SmoothPagedView // NOTE: When 'success' is true, onDragExit is called by the DragController before // calling onDropCompleted(). We call it ourselves here, but maybe this should be // moved into DragController.cancelDrag(). - doDragExit(); + doDragExit(null); ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell, false); } mLauncher.unlockScreenOrientation(); @@ -3368,6 +3445,7 @@ public class Workspace extends SmoothPagedView final int page = mCurrentPage + (direction == DragController.SCROLL_LEFT ? -1 : 1); final CellLayout layout = (CellLayout) getChildAt(page); + cancelFolderCreation(); if (layout != null) { layout.setIsDragOverlapping(true); |