1 /* 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 17 package com.android.documentsui.dirlist; 18 19 import static com.android.documentsui.base.SharedMinimal.DEBUG; 20 21 import android.app.Activity; 22 import android.content.ClipData; 23 import android.util.Log; 24 import android.view.DragEvent; 25 import android.view.View; 26 27 import androidx.recyclerview.selection.SelectionTracker; 28 29 import com.android.documentsui.AbstractActionHandler; 30 import com.android.documentsui.AbstractDragHost; 31 import com.android.documentsui.ActionHandler; 32 import com.android.documentsui.DragAndDropManager; 33 import com.android.documentsui.base.DocumentInfo; 34 import com.android.documentsui.base.DocumentStack; 35 import com.android.documentsui.base.Lookup; 36 import com.android.documentsui.base.State; 37 import com.android.documentsui.ui.DialogController; 38 39 import java.util.function.Predicate; 40 41 /** 42 * Drag host for items in {@link DirectoryFragment}. 43 */ 44 class DragHost<T extends Activity & AbstractActionHandler.CommonAddons> extends AbstractDragHost { 45 46 private static final String TAG = "dirlist.DragHost"; 47 48 private final T mActivity; 49 private final SelectionTracker<String> mSelectionMgr; 50 private final ActionHandler mActions; 51 private final State mState; 52 private final DialogController mDialogs; 53 private final Predicate<View> mIsDocumentView; 54 private final Lookup<View, DocumentHolder> mHolderLookup; 55 private final Lookup<View, DocumentInfo> mDestinationLookup; 56 DragHost( T activity, DragAndDropManager dragAndDropManager, SelectionTracker<String> selectionMgr, ActionHandler actions, State state, DialogController dialogs, Predicate<View> isDocumentView, Lookup<View, DocumentHolder> holderLookup, Lookup<View, DocumentInfo> destinationLookup)57 DragHost( 58 T activity, 59 DragAndDropManager dragAndDropManager, 60 SelectionTracker<String> selectionMgr, 61 ActionHandler actions, 62 State state, 63 DialogController dialogs, 64 Predicate<View> isDocumentView, 65 Lookup<View, DocumentHolder> holderLookup, 66 Lookup<View, DocumentInfo> destinationLookup) { 67 super(dragAndDropManager); 68 69 mActivity = activity; 70 mSelectionMgr = selectionMgr; 71 mActions = actions; 72 mState = state; 73 mDialogs = dialogs; 74 mIsDocumentView = isDocumentView; 75 mHolderLookup = holderLookup; 76 mDestinationLookup = destinationLookup; 77 } 78 dragStopped(boolean result)79 void dragStopped(boolean result) { 80 if (result) { 81 mSelectionMgr.clearSelection(); 82 } 83 } 84 85 @Override runOnUiThread(Runnable runnable)86 public void runOnUiThread(Runnable runnable) { 87 mActivity.runOnUiThread(runnable); 88 } 89 90 @Override setDropTargetHighlight(View v, boolean highlight)91 public void setDropTargetHighlight(View v, boolean highlight) { 92 } 93 94 @Override onViewHovered(View v)95 public void onViewHovered(View v) { 96 if (mIsDocumentView.test(v)) { 97 mActions.springOpenDirectory(mDestinationLookup.lookup(v)); 98 } 99 mActivity.setRootsDrawerOpen(false); 100 } 101 102 @Override onDragEntered(View v)103 public void onDragEntered(View v) { 104 mActivity.setRootsDrawerOpen(false); 105 mDragAndDropManager.updateState(v, mState.stack.getRoot(), mDestinationLookup.lookup(v)); 106 } 107 canSpringOpen(View v)108 boolean canSpringOpen(View v) { 109 DocumentInfo doc = mDestinationLookup.lookup(v); 110 return (doc != null) && mDragAndDropManager.canSpringOpen(mState.stack.getRoot(), doc); 111 } 112 handleDropEvent(View v, DragEvent event)113 boolean handleDropEvent(View v, DragEvent event) { 114 mActivity.setRootsDrawerOpen(false); 115 116 ClipData clipData = event.getClipData(); 117 assert (clipData != null); 118 119 DocumentInfo dst = mDestinationLookup.lookup(v); 120 if (dst == null) { 121 if (DEBUG) { 122 Log.d(TAG, "Invalid destination. Ignoring."); 123 } 124 return false; 125 } 126 127 // If destination is already at top of stack, no need to pass it in 128 DocumentStack dstStack = dst.equals(mState.stack.peek()) 129 ? mState.stack 130 : new DocumentStack(mState.stack, dst); 131 return mDragAndDropManager.drop(event.getClipData(), event.getLocalState(), dstStack, 132 mDialogs::showFileOperationStatus); 133 } 134 } 135