blob: 9638a75d8db9674c4a285efd347672881f2241df [file] [log] [blame]
Sunny Goyal027fba32017-06-19 15:30:19 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.launcher3.dragndrop;
18
Sunny Goyald3864fa2017-11-14 15:06:36 -080019import static com.android.launcher3.LauncherState.NORMAL;
20
Sunny Goyal027fba32017-06-19 15:30:19 -070021import android.content.ClipDescription;
22import android.content.Intent;
23import android.graphics.Point;
24import android.graphics.Rect;
25import android.os.Handler;
26import android.os.Looper;
Sunny Goyal027fba32017-06-19 15:30:19 -070027import android.os.SystemClock;
28import android.util.Log;
29import android.view.DragEvent;
30import android.view.View;
31
Sunny Goyald3864fa2017-11-14 15:06:36 -080032import com.android.launcher3.AbstractFloatingView;
Sunny Goyal027fba32017-06-19 15:30:19 -070033import com.android.launcher3.DragSource;
Sunny Goyal1797af42017-10-06 13:29:57 -070034import com.android.launcher3.DropTarget.DragObject;
Sunny Goyal027fba32017-06-19 15:30:19 -070035import com.android.launcher3.Launcher;
36import com.android.launcher3.R;
Sunny Goyald3864fa2017-11-14 15:06:36 -080037import com.android.launcher3.states.InternalStateHandler;
Sunny Goyal027fba32017-06-19 15:30:19 -070038import com.android.launcher3.widget.PendingItemDragHelper;
39
40import java.util.UUID;
41
42/**
43 * {@link DragSource} for handling drop from a different window.
44 */
Sunny Goyald3864fa2017-11-14 15:06:36 -080045public abstract class BaseItemDragListener extends InternalStateHandler implements
Sunny Goyal027fba32017-06-19 15:30:19 -070046 View.OnDragListener, DragSource, DragOptions.PreDragCondition {
47
48 private static final String TAG = "BaseItemDragListener";
49
50 private static final String MIME_TYPE_PREFIX = "com.android.launcher3.drag_and_drop/";
51 public static final String EXTRA_PIN_ITEM_DRAG_LISTENER = "pin_item_drag_listener";
52
53 // Position of preview relative to the touch location
54 private final Rect mPreviewRect;
55
56 private final int mPreviewBitmapWidth;
57 private final int mPreviewViewWidth;
58
59 // Randomly generated id used to verify the drag event.
60 private final String mId;
61
62 protected Launcher mLauncher;
63 private DragController mDragController;
64 private long mDragStartTime;
65
66 public BaseItemDragListener(Rect previewRect, int previewBitmapWidth, int previewViewWidth) {
67 mPreviewRect = previewRect;
68 mPreviewBitmapWidth = previewBitmapWidth;
69 mPreviewViewWidth = previewViewWidth;
70 mId = UUID.randomUUID().toString();
71 }
72
Sunny Goyal027fba32017-06-19 15:30:19 -070073 public String getMimeType() {
74 return MIME_TYPE_PREFIX + mId;
75 }
76
Sunny Goyald3864fa2017-11-14 15:06:36 -080077 @Override
Winson Chung1a341002018-01-17 10:00:23 -080078 public boolean init(Launcher launcher, boolean alreadyOnHome) {
Sunny Goyald3864fa2017-11-14 15:06:36 -080079 AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
80 launcher.getStateManager().goToState(NORMAL, alreadyOnHome /* animated */);
81 launcher.getDragLayer().setOnDragListener(this);
82
Sunny Goyal027fba32017-06-19 15:30:19 -070083 mLauncher = launcher;
84 mDragController = launcher.getDragController();
Winson Chung1a341002018-01-17 10:00:23 -080085 return false;
Sunny Goyal027fba32017-06-19 15:30:19 -070086 }
87
88 @Override
89 public boolean onDrag(View view, DragEvent event) {
90 if (mLauncher == null || mDragController == null) {
91 postCleanup();
92 return false;
93 }
94 if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
95 if (onDragStart(event)) {
96 return true;
97 } else {
98 postCleanup();
99 return false;
100 }
101 }
102 return mDragController.onDragEvent(mDragStartTime, event);
103 }
104
105 protected boolean onDragStart(DragEvent event) {
106 ClipDescription desc = event.getClipDescription();
107 if (desc == null || !desc.hasMimeType(getMimeType())) {
108 Log.e(TAG, "Someone started a dragAndDrop before us.");
109 return false;
110 }
111
112 Point downPos = new Point((int) event.getX(), (int) event.getY());
113 DragOptions options = new DragOptions();
114 options.systemDndStartPoint = downPos;
115 options.preDragCondition = this;
116
117 // We use drag event position as the screenPos for the preview image. Since mPreviewRect
118 // already includes the view position relative to the drag event on the source window,
119 // and the absolute position (position relative to the screen) of drag event is same
120 // across windows, using drag position here give a good estimate for relative position
121 // to source window.
122 createDragHelper().startDrag(new Rect(mPreviewRect),
123 mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
124 mDragStartTime = SystemClock.uptimeMillis();
125 return true;
126 }
127
128 protected abstract PendingItemDragHelper createDragHelper();
129
130 @Override
131 public boolean shouldStartDrag(double distanceDragged) {
132 // Stay in pre-drag mode, if workspace is locked.
133 return !mLauncher.isWorkspaceLocked();
134 }
135
136 @Override
Sunny Goyal1797af42017-10-06 13:29:57 -0700137 public void onPreDragStart(DragObject dragObject) {
Sunny Goyal027fba32017-06-19 15:30:19 -0700138 // The predrag starts when the workspace is not yet loaded. In some cases we set
139 // the dragLayer alpha to 0 to have a nice fade-in animation. But that will prevent the
140 // dragView from being visible. Instead just skip the fade-in animation here.
141 mLauncher.getDragLayer().setAlpha(1);
142
143 dragObject.dragView.setColor(
144 mLauncher.getResources().getColor(R.color.delete_target_hover_tint));
145 }
146
147 @Override
Sunny Goyal1797af42017-10-06 13:29:57 -0700148 public void onPreDragEnd(DragObject dragObject, boolean dragStarted) {
Sunny Goyal027fba32017-06-19 15:30:19 -0700149 if (dragStarted) {
150 dragObject.dragView.setColor(0);
151 }
152 }
153
154 @Override
Sunny Goyal1797af42017-10-06 13:29:57 -0700155 public void onDropCompleted(View target, DragObject d, boolean success) {
Sunny Goyal027fba32017-06-19 15:30:19 -0700156 postCleanup();
157 }
158
159 private void postCleanup() {
160 if (mLauncher != null) {
161 // Remove any drag params from the launcher intent since the drag operation is complete.
162 Intent newIntent = new Intent(mLauncher.getIntent());
163 newIntent.removeExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
164 mLauncher.setIntent(newIntent);
165 }
166
167 new Handler(Looper.getMainLooper()).post(new Runnable() {
168 @Override
169 public void run() {
170 removeListener();
171 }
172 });
173 }
174
175 public void removeListener() {
176 if (mLauncher != null) {
177 mLauncher.getDragLayer().setOnDragListener(null);
178 }
179 }
Sunny Goyal027fba32017-06-19 15:30:19 -0700180}