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;
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";
// 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;
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();
}
public void writeToParcel(Parcel parcel, int i) {
mRequest.writeToParcel(parcel, i);
mPreviewRect.writeToParcel(parcel, i);
+ parcel.writeInt(mPreviewBitmapWidth);
+ parcel.writeInt(mPreviewViewWidth);
parcel.writeString(mId);
}
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;
}
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() {
}
}
+ 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) {