blob: 4629dad3a2130e924d34955fb28d1a6950b115e8 [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
78 public void init(Launcher launcher, boolean alreadyOnHome) {
79 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();
85 }
86
87 @Override
88 public boolean onDrag(View view, DragEvent event) {
89 if (mLauncher == null || mDragController == null) {
90 postCleanup();
91 return false;
92 }
93 if (event.getAction() == DragEvent.ACTION_DRAG_STARTED) {
94 if (onDragStart(event)) {
95 return true;
96 } else {
97 postCleanup();
98 return false;
99 }
100 }
101 return mDragController.onDragEvent(mDragStartTime, event);
102 }
103
104 protected boolean onDragStart(DragEvent event) {
105 ClipDescription desc = event.getClipDescription();
106 if (desc == null || !desc.hasMimeType(getMimeType())) {
107 Log.e(TAG, "Someone started a dragAndDrop before us.");
108 return false;
109 }
110
111 Point downPos = new Point((int) event.getX(), (int) event.getY());
112 DragOptions options = new DragOptions();
113 options.systemDndStartPoint = downPos;
114 options.preDragCondition = this;
115
116 // We use drag event position as the screenPos for the preview image. Since mPreviewRect
117 // already includes the view position relative to the drag event on the source window,
118 // and the absolute position (position relative to the screen) of drag event is same
119 // across windows, using drag position here give a good estimate for relative position
120 // to source window.
121 createDragHelper().startDrag(new Rect(mPreviewRect),
122 mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
123 mDragStartTime = SystemClock.uptimeMillis();
124 return true;
125 }
126
127 protected abstract PendingItemDragHelper createDragHelper();
128
129 @Override
130 public boolean shouldStartDrag(double distanceDragged) {
131 // Stay in pre-drag mode, if workspace is locked.
132 return !mLauncher.isWorkspaceLocked();
133 }
134
135 @Override
Sunny Goyal1797af42017-10-06 13:29:57 -0700136 public void onPreDragStart(DragObject dragObject) {
Sunny Goyal027fba32017-06-19 15:30:19 -0700137 // The predrag starts when the workspace is not yet loaded. In some cases we set
138 // the dragLayer alpha to 0 to have a nice fade-in animation. But that will prevent the
139 // dragView from being visible. Instead just skip the fade-in animation here.
140 mLauncher.getDragLayer().setAlpha(1);
141
142 dragObject.dragView.setColor(
143 mLauncher.getResources().getColor(R.color.delete_target_hover_tint));
144 }
145
146 @Override
Sunny Goyal1797af42017-10-06 13:29:57 -0700147 public void onPreDragEnd(DragObject dragObject, boolean dragStarted) {
Sunny Goyal027fba32017-06-19 15:30:19 -0700148 if (dragStarted) {
149 dragObject.dragView.setColor(0);
150 }
151 }
152
153 @Override
Sunny Goyal1797af42017-10-06 13:29:57 -0700154 public void onDropCompleted(View target, DragObject d, boolean success) {
Sunny Goyal027fba32017-06-19 15:30:19 -0700155 postCleanup();
156 }
157
158 private void postCleanup() {
159 if (mLauncher != null) {
160 // Remove any drag params from the launcher intent since the drag operation is complete.
161 Intent newIntent = new Intent(mLauncher.getIntent());
162 newIntent.removeExtra(EXTRA_PIN_ITEM_DRAG_LISTENER);
163 mLauncher.setIntent(newIntent);
164 }
165
166 new Handler(Looper.getMainLooper()).post(new Runnable() {
167 @Override
168 public void run() {
169 removeListener();
170 }
171 });
172 }
173
174 public void removeListener() {
175 if (mLauncher != null) {
176 mLauncher.getDragLayer().setOnDragListener(null);
177 }
178 }
Sunny Goyald3864fa2017-11-14 15:06:36 -0800179
180 @Override
181 public void onLauncherResume() { }
Sunny Goyal027fba32017-06-19 15:30:19 -0700182}