OSDN Git Service

Fixing icon left on the workspace when drag operation fails
[android-x86/packages-apps-Launcher3.git] / src / com / android / launcher3 / dragndrop / PinItemDragListener.java
index 1a99cc8..df0c47c 100644 (file)
 
 package com.android.launcher3.dragndrop;
 
+import android.appwidget.AppWidgetManager;
 import android.content.ClipDescription;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
+import android.content.Intent;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcel;
@@ -30,32 +30,33 @@ import android.os.SystemClock;
 import android.util.Log;
 import android.view.DragEvent;
 import android.view.View;
+import android.widget.RemoteViews;
 
 import com.android.launcher3.DeleteDropTarget;
-import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.R;
 import com.android.launcher3.compat.PinItemRequestCompat;
 import com.android.launcher3.folder.Folder;
-import com.android.launcher3.graphics.LauncherIcons;
-import com.android.launcher3.shortcuts.ShortcutInfoCompat;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 import com.android.launcher3.widget.PendingAddShortcutInfo;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
-import com.android.launcher3.widget.PendingItemPreviewProvider;
+import com.android.launcher3.widget.PendingItemDragHelper;
+import com.android.launcher3.widget.WidgetAddFlowHandler;
 
 import java.util.UUID;
 
 /**
- * {@link DragSource} for handling drop from from a different window. This object is initialized
+ * {@link DragSource} for handling drop from a different window. This object is initialized
  * in the source window and is passed on to the Launcher activity as an Intent extra.
  */
-public class PinItemDragListener implements Parcelable, View.OnDragListener, DragSource {
+public class PinItemDragListener
+        implements Parcelable, View.OnDragListener, DragSource, DragOptions.PreDragCondition {
 
     private static final String TAG = "PinItemDragListener";
 
@@ -67,6 +68,9 @@ public class PinItemDragListener implements Parcelable, View.OnDragListener, Dra
     // Position of preview relative to the touch location
     private final Rect mPreviewRect;
 
+    private final int mPreviewBitmapWidth;
+    private final int mPreviewViewWidth;
+
     // Randomly generated id used to verify the drag event.
     private final String mId;
 
@@ -74,15 +78,20 @@ public class PinItemDragListener implements Parcelable, View.OnDragListener, Dra
     private DragController mDragController;
     private long mDragStartTime;
 
-    public PinItemDragListener(PinItemRequestCompat request, Rect previewRect) {
+    public PinItemDragListener(PinItemRequestCompat request, Rect previewRect,
+            int previewBitmapWidth, int previewViewWidth) {
         mRequest = request;
         mPreviewRect = previewRect;
+        mPreviewBitmapWidth = previewBitmapWidth;
+        mPreviewViewWidth = previewViewWidth;
         mId = UUID.randomUUID().toString();
     }
 
     private PinItemDragListener(Parcel parcel) {
         mRequest = PinItemRequestCompat.CREATOR.createFromParcel(parcel);
         mPreviewRect = Rect.CREATOR.createFromParcel(parcel);
+        mPreviewBitmapWidth = parcel.readInt();
+        mPreviewViewWidth = parcel.readInt();
         mId = parcel.readString();
     }
 
@@ -99,6 +108,8 @@ public class PinItemDragListener implements Parcelable, View.OnDragListener, Dra
     public void writeToParcel(Parcel parcel, int i) {
         mRequest.writeToParcel(parcel, i);
         mPreviewRect.writeToParcel(parcel, i);
+        parcel.writeInt(mPreviewBitmapWidth);
+        parcel.writeInt(mPreviewViewWidth);
         parcel.writeString(mId);
     }
 
@@ -134,70 +145,73 @@ public class PinItemDragListener implements Parcelable, View.OnDragListener, Dra
             return false;
         }
 
-        if (mLauncher.isWorkspaceLocked()) {
-            // TODO: implement wait
-            return false;
-        }
-
         final PendingAddItemInfo item;
-        final Bitmap preview;
-
-        Point dragShift = new Point(mPreviewRect.left, mPreviewRect.top);
         if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) {
             item = new PendingAddShortcutInfo(
                     new PinShortcutRequestActivityInfo(mRequest, mLauncher));
-
-            ShortcutInfoCompat compat = new ShortcutInfoCompat(mRequest.getShortcutInfo());
-            Bitmap icon = LauncherIcons.createShortcutIcon(compat, mLauncher, false /* badged */);
-
-            // Create a preview same as the workspace cell size and draw the icon at the
-            // appropriate position.
-            int[] size = mLauncher.getWorkspace().estimateItemSize(item, true, false);
-            preview = Bitmap.createBitmap(size[0], size[1], Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(preview);
-            DeviceProfile dp = mLauncher.getDeviceProfile();
-            c.drawBitmap(icon, (size[0] - icon.getWidth()) / 2,
-                    (size[1] - icon.getHeight() - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2,
-                    new Paint(Paint.FILTER_BITMAP_FLAG));
         } else {
-            PendingAddWidgetInfo info = new PendingAddWidgetInfo(
+            // mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_APPWIDGET
+            LauncherAppWidgetProviderInfo providerInfo =
                     LauncherAppWidgetProviderInfo.fromProviderInfo(
-                            mLauncher, mRequest.getAppWidgetProviderInfo(mLauncher)));
-            int[] size = mLauncher.getWorkspace().estimateItemSize(info, true, false);
-
-            float minScale = 1.25f;
-            int maxWidth = Math.min((int) (mPreviewRect.width() * minScale), size[0]);
-            int[] previewSizeBeforeScale = new int[1];
-            preview = LauncherAppState.getInstance(mLauncher).getWidgetCache()
-                    .generateWidgetPreview(mLauncher, info.info, maxWidth, null,
-                            previewSizeBeforeScale);
-
-            dragShift.offset(
-                    (mPreviewRect.width() - preview.getWidth()) / 2,
-                    (mPreviewRect.height() - preview.getHeight()) / 2);
-            item = info;
+                            mLauncher, mRequest.getAppWidgetProviderInfo(mLauncher));
+            final PinWidgetFlowHandler flowHandler =
+                    new PinWidgetFlowHandler(providerInfo, mRequest);
+            item = new PendingAddWidgetInfo(providerInfo) {
+                @Override
+                public WidgetAddFlowHandler getHandler() {
+                    return flowHandler;
+                }
+            };
         }
-
-        PendingItemPreviewProvider previewProvider =
-                new PendingItemPreviewProvider(new View(mLauncher), item, preview);
-
-        // Since we are not going through the workspace for starting the drag, set drag related
-        // information on the workspace before starting the drag.
-        mLauncher.getWorkspace().prepareDragWithProvider(previewProvider);
+        View view = new View(mLauncher);
+        view.setTag(item);
 
         Point downPos = new Point((int) event.getX(), (int) event.getY());
         DragOptions options = new DragOptions();
         options.systemDndStartPoint = downPos;
+        options.preDragCondition = this;
+
+        // We use drag event position as the screenPos for the preview image. Since mPreviewRect
+        // already includes the view position relative to the drag event on the source window,
+        // and the absolute position (position relative to the screen) of drag event is same
+        // across windows, using drag position here give a good estimate for relative position
+        // to source window.
+        PendingItemDragHelper dragHelper = new PendingItemDragHelper(view);
+        if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_APPWIDGET) {
+            dragHelper.setPreview(getPreview(mRequest));
+        }
 
-        int x = downPos.x + dragShift.x;
-        int y = downPos.y + dragShift.y;
-        mDragController.startDrag(
-                preview, x, y, this, item, null, null, 1f, options);
+        dragHelper.startDrag(new Rect(mPreviewRect),
+                mPreviewBitmapWidth, mPreviewViewWidth, downPos,  this, options);
         mDragStartTime = SystemClock.uptimeMillis();
         return true;
     }
 
     @Override
+    public boolean shouldStartDrag(double distanceDragged) {
+        // Stay in pre-drag mode, if workspace is locked.
+        return !mLauncher.isWorkspaceLocked();
+    }
+
+    @Override
+    public void onPreDragStart(DropTarget.DragObject dragObject) {
+        // The predrag starts when the workspace is not yet loaded. In some cases we set
+        // the dragLayer alpha to 0 to have a nice fade-in animation. But that will prevent the
+        // dragView from being visible. Instead just skip the fade-in animation here.
+        mLauncher.getDragLayer().setAlpha(1);
+
+        dragObject.dragView.setColor(
+                mLauncher.getResources().getColor(R.color.delete_target_hover_tint));
+    }
+
+    @Override
+    public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
+        if (dragStarted) {
+            dragObject.dragView.setColor(0);
+        }
+    }
+
+    @Override
     public boolean supportsAppInfoDropTarget() {
         return false;
     }
@@ -222,16 +236,27 @@ public class PinItemDragListener implements Parcelable, View.OnDragListener, Dra
             mLauncher.exitSpringLoadedDragModeDelayed(true,
                     Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
         }
+
+        if (!success) {
+            d.deferDragViewCleanupPostAnimation = false;
+        }
         postCleanup();
     }
 
     @Override
     public void fillInLogContainerData(View v, ItemInfo info, LauncherLogProto.Target target,
             LauncherLogProto.Target targetParent) {
-        // TODO: We should probably log something
+        targetParent.containerType = ContainerType.PINITEM;
     }
 
     private void postCleanup() {
+        if (mLauncher != null) {
+            // Remove any drag params from the launcher intent since the drag operation is complete.
+            Intent newIntent = new Intent(mLauncher.getIntent());
+            newIntent.removeExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
+            mLauncher.setIntent(newIntent);
+        }
+
         new Handler(Looper.getMainLooper()).post(new Runnable() {
             @Override
             public void run() {
@@ -246,6 +271,30 @@ public class PinItemDragListener implements Parcelable, View.OnDragListener, Dra
         }
     }
 
+    public static RemoteViews getPreview(PinItemRequestCompat request) {
+        Bundle extras = request.getExtras();
+        if (extras != null &&
+                extras.get(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW) instanceof RemoteViews) {
+            return (RemoteViews) extras.get(AppWidgetManager.EXTRA_APPWIDGET_PREVIEW);
+        }
+        return null;
+    }
+
+    public static boolean handleDragRequest(Launcher launcher, Intent intent) {
+        if (intent == null || !Intent.ACTION_MAIN.equals(intent.getAction())) {
+            return false;
+        }
+        Parcelable dragExtra = intent.getParcelableExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
+        if (dragExtra instanceof PinItemDragListener) {
+            PinItemDragListener dragListener = (PinItemDragListener) dragExtra;
+            dragListener.setLauncher(launcher);
+
+            launcher.getDragLayer().setOnDragListener(dragListener);
+            return true;
+        }
+        return false;
+    }
+
     public static final Parcelable.Creator<PinItemDragListener> CREATOR =
             new Parcelable.Creator<PinItemDragListener>() {
                 public PinItemDragListener createFromParcel(Parcel source) {