summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/dragndrop/DragDriver.java
diff options
context:
space:
mode:
authorVadim Tryshev <vadimt@google.com>2015-08-19 17:55:02 -0700
committerVadim Tryshev <vadimt@google.com>2015-08-20 07:45:57 -0700
commitfedca43d396d6fd7c46fbb2f37dfa7cfe3b31834 (patch)
tree111a7ede5c82806b82b47f7ba5b827750796f5b1 /src/com/android/launcher3/dragndrop/DragDriver.java
parent08efde7e247690a71c523df33b078ab530454bbe (diff)
downloadandroid_packages_apps_Trebuchet-fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834.tar.gz
android_packages_apps_Trebuchet-fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834.tar.bz2
android_packages_apps_Trebuchet-fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834.zip
Moving drag-drop related code into a separate package.
This is per an earlier CR comment "we should probably move all this code to its own package (launcher3.dragndrop) in a separate cl". I'm not moving DragSource because it's referred from gsa code. Bug: 22609426 Change-Id: Ia7204dab99c0c395c66b77143a2d60411153f5f3
Diffstat (limited to 'src/com/android/launcher3/dragndrop/DragDriver.java')
-rw-r--r--src/com/android/launcher3/dragndrop/DragDriver.java250
1 files changed, 250 insertions, 0 deletions
diff --git a/src/com/android/launcher3/dragndrop/DragDriver.java b/src/com/android/launcher3/dragndrop/DragDriver.java
new file mode 100644
index 000000000..6e4b430d4
--- /dev/null
+++ b/src/com/android/launcher3/dragndrop/DragDriver.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.dragndrop;
+
+import com.android.launcher3.AnotherWindowDropTarget;
+import com.android.launcher3.DropTarget;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.Utilities;
+
+import android.content.ClipData;
+import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.Point;
+import android.view.DragEvent;
+import android.view.MotionEvent;
+import android.view.View;
+
+/**
+ * Base class for driving a drag/drop operation.
+ */
+public abstract class DragDriver {
+ protected final EventListener mEventListener;
+
+ public interface EventListener {
+ void onDriverDragMove(float x, float y);
+ void onDriverDragExitWindow();
+ void onDriverDragEnd(float x, float y, DropTarget dropTargetOverride);
+ void onDriverDragCancel();
+ }
+
+ public DragDriver(EventListener eventListener) {
+ mEventListener = eventListener;
+ }
+
+ /**
+ * Handles ending of the DragView animation.
+ */
+ public abstract void onDragViewAnimationEnd();
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ final int action = ev.getAction();
+
+ switch (action) {
+ case MotionEvent.ACTION_MOVE:
+ mEventListener.onDriverDragMove(ev.getX(), ev.getY());
+ break;
+ case MotionEvent.ACTION_UP:
+ mEventListener.onDriverDragMove(ev.getX(), ev.getY());
+ mEventListener.onDriverDragEnd(ev.getX(), ev.getY(), null);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ mEventListener.onDriverDragCancel();
+ break;
+ }
+
+ return true;
+ }
+
+ public abstract boolean onDragEvent (DragEvent event);
+
+
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ final int action = ev.getAction();
+
+ switch (action) {
+ case MotionEvent.ACTION_UP:
+ mEventListener.onDriverDragEnd(ev.getX(), ev.getY(), null);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ mEventListener.onDriverDragCancel();
+ break;
+ }
+
+ return true;
+ }
+
+ public static DragDriver create(
+ DragController dragController, ItemInfo dragInfo, DragView dragView) {
+ if (Utilities.isNycOrAbove()) {
+ return new SystemDragDriver(dragController, dragInfo.getIntent(), dragView);
+ } else {
+ return new InternalDragDriver(dragController);
+ }
+ }
+
+};
+
+/**
+ * Class for driving a system (i.e. framework) drag/drop operation.
+ */
+class SystemDragDriver extends DragDriver {
+ /** Intent associated with the drag operation, or null is there no associated intent. */
+ private final Intent mDragIntent;
+
+ private final DragView mDragView;
+ boolean mIsFrameworkDragActive = false;
+ boolean mReceivedDropEvent = false;
+ float mLastX = 0;
+ float mLastY = 0;
+
+ public SystemDragDriver(DragController dragController, Intent dragIntent, DragView dragView) {
+ super(dragController);
+ mDragIntent = dragIntent;
+ mDragView = dragView;
+ }
+
+ private static class ShadowBuilder extends View.DragShadowBuilder {
+ final DragView mDragView;
+
+ public ShadowBuilder(DragView dragView) {
+ mDragView = dragView;
+ }
+
+ @Override
+ public void onProvideShadowMetrics (Point size, Point touch) {
+ mDragView.provideDragShadowMetrics(size, touch);
+ }
+
+ @Override
+ public void onDrawShadow(Canvas canvas) {
+ mDragView.drawDragShadow(canvas);
+ }
+ };
+
+ @Override
+ public void onDragViewAnimationEnd() {
+ // Clip data for the drag operation. If there is an intent, create an intent-based ClipData,
+ // which will be passed to a global DND.
+ // If there is no intent, craft a fake ClipData and start a local DND operation; this
+ // ClipData will be ignored.
+ final ClipData dragData = mDragIntent != null ?
+ ClipData.newIntent("", mDragIntent) :
+ ClipData.newPlainText("", "");
+
+ View.DragShadowBuilder shadowBuilder = new ShadowBuilder(mDragView);
+ // TODO: DND flags are in flux, once settled, use the appropriate constant.
+ final int flagGlobal = 1 << 0;
+ final int flagOpaque = 1 << 9;
+ final int flags = (mDragIntent != null ? flagGlobal : 0) | flagOpaque;
+
+ mIsFrameworkDragActive = true;
+
+ if (!mDragView.startDrag(dragData, shadowBuilder, null, flags)) {
+ mIsFrameworkDragActive = false;
+ mEventListener.onDriverDragCancel();
+ return;
+ }
+
+ // Starting from this point, the driver takes over showing the drag shadow, so hiding the
+ // drag view.
+ mDragView.setVisibility(View.INVISIBLE);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return !mIsFrameworkDragActive && super.onTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ return !mIsFrameworkDragActive && super.onInterceptTouchEvent(ev);
+ }
+
+ @Override
+ public boolean onDragEvent (DragEvent event) {
+ if (!mIsFrameworkDragActive) {
+ // We are interested only in drag events started by this driver.
+ return false;
+ }
+
+ final int action = event.getAction();
+
+ switch (action) {
+ case DragEvent.ACTION_DRAG_STARTED:
+ mLastX = event.getX();
+ mLastY = event.getY();
+ return true;
+
+ case DragEvent.ACTION_DRAG_ENTERED:
+ mLastX = event.getX();
+ mLastY = event.getY();
+ return true;
+
+ case DragEvent.ACTION_DRAG_LOCATION:
+ mLastX = event.getX();
+ mLastY = event.getY();
+ mEventListener.onDriverDragMove(event.getX(), event.getY());
+ return true;
+
+ case DragEvent.ACTION_DROP:
+ mLastX = event.getX();
+ mLastY = event.getY();
+ mReceivedDropEvent = true;
+ return true;
+
+ case DragEvent.ACTION_DRAG_EXITED:
+ mLastX = event.getX();
+ mLastY = event.getY();
+ mEventListener.onDriverDragExitWindow();
+ return true;
+
+ case DragEvent.ACTION_DRAG_ENDED:
+ final boolean dragAccepted = event.getResult();
+ final boolean acceptedByAnotherWindow = dragAccepted && !mReceivedDropEvent;
+
+ // When the system drag ends, its drag shadow disappears. Resume showing the drag
+ // view for the possible final animation.
+ mDragView.setVisibility(View.VISIBLE);
+
+ final DropTarget dropTargetOverride = acceptedByAnotherWindow ?
+ new AnotherWindowDropTarget(mDragView.getContext()) : null;
+
+ mEventListener.onDriverDragEnd(mLastX, mLastY, dropTargetOverride);
+ mIsFrameworkDragActive = false;
+ return true;
+
+ default:
+ return false;
+ }
+ }
+};
+
+/**
+ * Class for driving an internal (i.e. not using framework) drag/drop operation.
+ */
+class InternalDragDriver extends DragDriver {
+ public InternalDragDriver(DragController dragController) {
+ super(dragController);
+ }
+
+ @Override
+ public void onDragViewAnimationEnd() {}
+
+ @Override
+ public boolean onDragEvent (DragEvent event) { return false; }
+};