• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.documentsui.dirlist;
17 
18 import static android.support.v4.util.Preconditions.checkArgument;
19 
20 import android.support.v7.widget.RecyclerView;
21 import android.support.v7.widget.RecyclerView.ViewHolder;
22 import android.view.HapticFeedbackConstants;
23 import android.view.KeyEvent;
24 import android.view.MotionEvent;
25 
26 import com.android.documentsui.ActionHandler;
27 import com.android.documentsui.base.EventHandler;
28 import com.android.documentsui.base.State;
29 import com.android.documentsui.selection.GestureSelectionHelper;
30 import com.android.documentsui.selection.ItemDetailsLookup;
31 import com.android.documentsui.selection.MouseInputHandler;
32 import com.android.documentsui.selection.SelectionHelper;
33 import com.android.documentsui.selection.TouchInputHandler;
34 import com.android.documentsui.selection.ItemDetailsLookup.ItemDetails;
35 import com.android.documentsui.selection.SelectionHelper.SelectionPredicate;
36 
37 /**
38  * Helper class dedicated to building gesture input handlers. The construction
39  * of the various input handlers is non trivial. To keep logic clear,
40  * code flexible, and DirectoryFragment small(er), the construction has been
41  * isolated here in a separate class.
42  */
43 final class InputHandlers {
44 
45     private ActionHandler mActions;
46     private SelectionHelper mSelectionHelper;
47     private SelectionPredicate mSelectionPredicate;
48     private ItemDetailsLookup mDetailsLookup;
49     private FocusHandler mFocusHandler;
50     private RecyclerView mRecView;
51     private State mState;
52 
InputHandlers( ActionHandler actions, SelectionHelper selectionHelper, SelectionPredicate selectionPredicate, ItemDetailsLookup detailsLookup, FocusHandler focusHandler, RecyclerView recView, State state)53     InputHandlers(
54             ActionHandler actions,
55             SelectionHelper selectionHelper,
56             SelectionPredicate selectionPredicate,
57             ItemDetailsLookup detailsLookup,
58             FocusHandler focusHandler,
59             RecyclerView recView,
60             State state) {
61 
62         checkArgument(actions != null);
63         checkArgument(selectionHelper != null);
64         checkArgument(selectionPredicate != null);
65         checkArgument(detailsLookup != null);
66         checkArgument(focusHandler != null);
67         checkArgument(recView != null);
68         checkArgument(state != null);
69 
70         mActions = actions;
71         mSelectionHelper = selectionHelper;
72         mSelectionPredicate = selectionPredicate;
73         mDetailsLookup = detailsLookup;
74         mFocusHandler = focusHandler;
75         mRecView = recView;
76         mState = state;
77     }
78 
createKeyHandler()79     KeyInputHandler createKeyHandler() {
80         KeyInputHandler.Callbacks callbacks = new KeyInputHandler.Callbacks() {
81             @Override
82             public boolean isInteractiveItem(ItemDetails item, KeyEvent e) {
83                 switch (item.getItemViewType()) {
84                     case DocumentsAdapter.ITEM_TYPE_HEADER_MESSAGE:
85                     case DocumentsAdapter.ITEM_TYPE_INFLATED_MESSAGE:
86                     case DocumentsAdapter.ITEM_TYPE_SECTION_BREAK:
87                         return false;
88                     case DocumentsAdapter.ITEM_TYPE_DOCUMENT:
89                     case DocumentsAdapter.ITEM_TYPE_DIRECTORY:
90                         return true;
91                     default:
92                         throw new RuntimeException(
93                                 "Unsupported item type: " + item.getItemViewType());
94                 }
95             }
96 
97             @Override
98             public boolean onItemActivated(ItemDetails item, KeyEvent e) {
99                 // Handle enter key events
100                 switch (e.getKeyCode()) {
101                     case KeyEvent.KEYCODE_ENTER:
102                     case KeyEvent.KEYCODE_DPAD_CENTER:
103                     case KeyEvent.KEYCODE_BUTTON_A:
104                         return mActions.openItem(
105                                 item,
106                                 ActionHandler.VIEW_TYPE_REGULAR,
107                                 ActionHandler.VIEW_TYPE_PREVIEW);
108                     case KeyEvent.KEYCODE_SPACE:
109                         return mActions.openItem(
110                                 item,
111                                 ActionHandler.VIEW_TYPE_PREVIEW,
112                                 ActionHandler.VIEW_TYPE_NONE);
113                 }
114 
115                 return false;
116             }
117 
118             @Override
119             public boolean onFocusItem(ItemDetails details, int keyCode, KeyEvent event) {
120                 ViewHolder holder =
121                         mRecView.findViewHolderForAdapterPosition(details.getPosition());
122                 if (holder instanceof DocumentHolder) {
123                     return mFocusHandler.handleKey((DocumentHolder) holder, keyCode, event);
124                 }
125                 return false;
126             }
127 
128             @Override
129             public void onPerformHapticFeedback() {
130                 mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
131             }
132         };
133 
134         return new KeyInputHandler(mSelectionHelper, mSelectionPredicate, callbacks);
135     }
136 
createMouseHandler( EventHandler<MotionEvent> showContextMenuCallback)137     MouseInputHandler createMouseHandler(
138             EventHandler<MotionEvent> showContextMenuCallback) {
139 
140         checkArgument(showContextMenuCallback != null);
141 
142         MouseInputHandler.Callbacks callbacks = new MouseInputHandler.Callbacks() {
143             @Override
144             public boolean onItemActivated(ItemDetails item, MotionEvent e) {
145                 return mActions.openItem(
146                         item,
147                         ActionHandler.VIEW_TYPE_REGULAR,
148                         ActionHandler.VIEW_TYPE_PREVIEW);
149             }
150 
151             @Override
152             public boolean onContextClick(MotionEvent e) {
153                 return showContextMenuCallback.accept(e);
154             }
155 
156             @Override
157             public void onPerformHapticFeedback() {
158                 mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
159             }
160 
161             @Override
162             public void focusItem(ItemDetails item) {
163                 mFocusHandler.focusDocument(item.getStableId());
164             }
165 
166             @Override
167             public void clearFocus() {
168                 mFocusHandler.clearFocus();
169             }
170 
171             @Override
172             public boolean hasFocusedItem() {
173                 return mFocusHandler.hasFocusedItem();
174             }
175 
176             @Override
177             public int getFocusedPosition() {
178                 return mFocusHandler.getFocusPosition();
179             }
180         };
181 
182         return new MouseInputHandler(mSelectionHelper, mDetailsLookup, callbacks);
183     }
184 
185     /**
186      * Factory method for input touch delegate. Exists to reduce complexity in the
187      * calling scope.
188      * @param gestureHelper
189      */
createTouchHandler( GestureSelectionHelper gestureHelper, DragStartListener dragStartListener)190     TouchInputHandler createTouchHandler(
191             GestureSelectionHelper gestureHelper, DragStartListener dragStartListener) {
192         checkArgument(dragStartListener != null);
193 
194         TouchInputHandler.Callbacks callbacks = new TouchInputHandler.Callbacks() {
195             @Override
196             public boolean onItemActivated(ItemDetails item, MotionEvent e) {
197                 return mActions.openItem(
198                         item,
199                         ActionHandler.VIEW_TYPE_PREVIEW,
200                         ActionHandler.VIEW_TYPE_REGULAR);
201             }
202 
203             @Override
204             public boolean onDragInitiated(MotionEvent e) {
205                 return dragStartListener.onTouchDragEvent(e);
206             }
207 
208             @Override
209             public void onPerformHapticFeedback() {
210                 mRecView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
211             }
212 
213             @Override
214             public void focusItem(ItemDetails item) {
215                 mFocusHandler.focusDocument(item.getStableId());
216             }
217 
218             @Override
219             public void clearFocus() {
220                 mFocusHandler.clearFocus();
221             }
222         };
223 
224         return new TouchInputHandler(
225                 mSelectionHelper, mDetailsLookup, mSelectionPredicate, gestureHelper, callbacks);
226     }
227 }
228