diff options
author | Vadim Tryshev <vadimt@google.com> | 2015-08-19 17:55:02 -0700 |
---|---|---|
committer | Vadim Tryshev <vadimt@google.com> | 2015-08-20 07:45:57 -0700 |
commit | fedca43d396d6fd7c46fbb2f37dfa7cfe3b31834 (patch) | |
tree | 111a7ede5c82806b82b47f7ba5b827750796f5b1 /src/com/android/launcher3/dragndrop/DragDriver.java | |
parent | 08efde7e247690a71c523df33b078ab530454bbe (diff) | |
download | android_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.java | 250 |
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; } +}; |