• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.files;
18 
19 import android.app.Fragment;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.net.Uri;
23 import android.view.KeyEvent;
24 import android.view.KeyboardShortcutGroup;
25 import android.view.KeyboardShortcutInfo;
26 import android.view.Menu;
27 import android.view.MenuInflater;
28 import android.view.MenuItem;
29 import android.view.View;
30 
31 import com.android.documentsui.R;
32 import com.android.documentsui.MenuManager.SelectionDetails;
33 import com.android.documentsui.base.DocumentInfo;
34 import com.android.documentsui.base.Features;
35 import com.android.documentsui.base.Lookup;
36 import com.android.documentsui.base.RootInfo;
37 import com.android.documentsui.base.State;
38 import com.android.documentsui.queries.SearchViewManager;
39 import com.android.documentsui.selection.SelectionHelper;
40 
41 import java.util.List;
42 import java.util.function.IntFunction;
43 
44 public final class MenuManager extends com.android.documentsui.MenuManager {
45 
46     private final Features mFeatures;
47     private final Context mContext;
48     private final SelectionHelper mSelectionManager;
49     private final Lookup<String, Uri> mUriLookup;
50     private final Lookup<String, String> mAppNameLookup;
51 
MenuManager( Features features, SearchViewManager searchManager, State displayState, DirectoryDetails dirDetails, Context context, SelectionHelper selectionManager, Lookup<String, String> appNameLookup, Lookup<String, Uri> uriLookup)52     public MenuManager(
53             Features features,
54             SearchViewManager searchManager,
55             State displayState,
56             DirectoryDetails dirDetails,
57             Context context,
58             SelectionHelper selectionManager,
59             Lookup<String, String> appNameLookup,
60             Lookup<String, Uri> uriLookup) {
61 
62         super(searchManager, displayState, dirDetails);
63 
64         mFeatures = features;
65         mContext = context;
66         mSelectionManager = selectionManager;
67         mAppNameLookup = appNameLookup;
68         mUriLookup = uriLookup;
69     }
70 
71     @Override
updateOptionMenu(Menu menu)72     public void updateOptionMenu(Menu menu) {
73         super.updateOptionMenu(menu);
74 
75         // It hides icon if searching in progress
76         mSearchManager.updateMenu();
77     }
78 
79     @Override
updateKeyboardShortcutsMenu( List<KeyboardShortcutGroup> data, IntFunction<String> stringSupplier)80     public void updateKeyboardShortcutsMenu(
81             List<KeyboardShortcutGroup> data, IntFunction<String> stringSupplier) {
82         KeyboardShortcutGroup group = new KeyboardShortcutGroup(
83                 stringSupplier.apply(R.string.app_label));
84         group.addItem(new KeyboardShortcutInfo(
85                 stringSupplier.apply(R.string.menu_cut_to_clipboard), KeyEvent.KEYCODE_X,
86                 KeyEvent.META_CTRL_ON));
87         group.addItem(new KeyboardShortcutInfo(
88                 stringSupplier.apply(R.string.menu_copy_to_clipboard), KeyEvent.KEYCODE_C,
89                 KeyEvent.META_CTRL_ON));
90         group.addItem(new KeyboardShortcutInfo(
91                 stringSupplier.apply(R.string.menu_paste_from_clipboard), KeyEvent.KEYCODE_V,
92                 KeyEvent.META_CTRL_ON));
93         group.addItem(new KeyboardShortcutInfo(
94                 stringSupplier.apply(R.string.menu_create_dir), KeyEvent.KEYCODE_E,
95                 KeyEvent.META_CTRL_ON));
96         group.addItem(new KeyboardShortcutInfo(
97                 stringSupplier.apply(R.string.menu_select_all), KeyEvent.KEYCODE_A,
98                 KeyEvent.META_CTRL_ON));
99         group.addItem(new KeyboardShortcutInfo(
100                 stringSupplier.apply(R.string.menu_new_window), KeyEvent.KEYCODE_N,
101                 KeyEvent.META_CTRL_ON));
102         data.add(group);
103     }
104 
105     @Override
showContextMenu(Fragment f, View v, float x, float y)106     public void showContextMenu(Fragment f, View v, float x, float y) {
107         // Register context menu here so long-press doesn't trigger this context floating menu.
108         f.registerForContextMenu(v);
109         v.showContextMenu(x, y);
110         f.unregisterForContextMenu(v);
111     }
112 
113     @Override
inflateContextMenuForContainer(Menu menu, MenuInflater inflater)114     public void inflateContextMenuForContainer(Menu menu, MenuInflater inflater) {
115         inflater.inflate(R.menu.container_context_menu, menu);
116         updateContextMenuForContainer(menu);
117     }
118 
119     @Override
inflateContextMenuForDocs( Menu menu, MenuInflater inflater, SelectionDetails selectionDetails)120     public void inflateContextMenuForDocs(
121             Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) {
122         final boolean hasDir = selectionDetails.containsDirectories();
123         final boolean hasFile = selectionDetails.containsFiles();
124 
125         assert(hasDir || hasFile);
126         if (!hasDir) {
127             inflater.inflate(R.menu.file_context_menu, menu);
128             updateContextMenuForFiles(menu, selectionDetails);
129             return;
130         }
131 
132         if (!hasFile) {
133             inflater.inflate(R.menu.dir_context_menu, menu);
134             updateContextMenuForDirs(menu, selectionDetails);
135             return;
136         }
137 
138         inflater.inflate(R.menu.mixed_context_menu, menu);
139         updateContextMenu(menu, selectionDetails);
140     }
141 
142     @Override
updateSettings(MenuItem settings, RootInfo root)143     protected void updateSettings(MenuItem settings, RootInfo root) {
144         settings.setVisible(true);
145         settings.setEnabled(root.hasSettings());
146     }
147 
148     @Override
updateEject(MenuItem eject, RootInfo root)149     protected void updateEject(MenuItem eject, RootInfo root) {
150         eject.setVisible(root.supportsEject());
151         eject.setEnabled(!root.ejecting);
152     }
153 
154     @Override
updateSettings(MenuItem settings)155     protected void updateSettings(MenuItem settings) {
156         boolean enabled = mDirDetails.hasRootSettings();
157         settings.setVisible(enabled);
158         settings.setEnabled(enabled);
159     }
160 
161     @Override
updateNewWindow(MenuItem newWindow)162     protected void updateNewWindow(MenuItem newWindow) {
163         newWindow.setVisible(true);
164     }
165 
166     @Override
updateOpenInContextMenu(MenuItem open, SelectionDetails selectionDetails)167     protected void updateOpenInContextMenu(MenuItem open, SelectionDetails selectionDetails) {
168         open.setVisible(true);
169         open.setEnabled(selectionDetails.size() == 1
170                 && !selectionDetails.containsPartialFiles());
171     }
172 
173     @Override
updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails)174     protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) {
175         openWith.setVisible(true);
176         openWith.setEnabled(selectionDetails.canOpenWith());
177     }
178 
179     @Override
updateOpenInNewWindow( MenuItem openInNewWindow, SelectionDetails selectionDetails)180     protected void updateOpenInNewWindow(
181             MenuItem openInNewWindow, SelectionDetails selectionDetails) {
182         openInNewWindow.setVisible(true);
183         openInNewWindow.setEnabled(selectionDetails.size() == 1
184             && !selectionDetails.containsPartialFiles());
185     }
186 
187     @Override
updateOpenInNewWindow(MenuItem openInNewWindow, RootInfo root)188     protected void updateOpenInNewWindow(MenuItem openInNewWindow, RootInfo root) {
189         assert(openInNewWindow.isVisible() && openInNewWindow.isEnabled());
190     }
191 
192     @Override
updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails)193     protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
194         moveTo.setVisible(true);
195         moveTo.setEnabled(!selectionDetails.containsPartialFiles() && selectionDetails.canDelete());
196     }
197 
198     @Override
updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails)199     protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
200         copyTo.setVisible(true);
201         copyTo.setEnabled(!selectionDetails.containsPartialFiles() &&
202                 !selectionDetails.canExtract());
203     }
204 
205     @Override
updateCompress(MenuItem compress, SelectionDetails selectionDetails)206     protected void updateCompress(MenuItem compress, SelectionDetails selectionDetails) {
207         final boolean readOnly = !mDirDetails.canCreateDoc();
208         compress.setVisible(mFeatures.isArchiveCreationEnabled());
209         compress.setEnabled(!readOnly && !selectionDetails.containsPartialFiles() &&
210                 !selectionDetails.canExtract());
211     }
212 
213     @Override
updateExtractTo(MenuItem extractTo, SelectionDetails selectionDetails)214     protected void updateExtractTo(MenuItem extractTo, SelectionDetails selectionDetails) {
215         boolean enabled = selectionDetails.canExtract();
216         extractTo.setVisible(enabled);
217         extractTo.setEnabled(enabled);
218     }
219 
220     @Override
updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails)221     protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) {
222         pasteInto.setVisible(true);
223         pasteInto.setEnabled(selectionDetails.canPasteInto() && mDirDetails.hasItemsToPaste());
224     }
225 
226     @Override
updatePasteInto(MenuItem pasteInto, RootInfo root, DocumentInfo docInfo)227     protected void updatePasteInto(MenuItem pasteInto, RootInfo root, DocumentInfo docInfo) {
228         pasteInto.setVisible(true);
229         pasteInto.setEnabled(root.supportsCreate()
230                 && docInfo != null
231                 && docInfo.isCreateSupported()
232                 && mDirDetails.hasItemsToPaste());
233     }
234 
235     @Override
updateSelectAll(MenuItem selectAll)236     protected void updateSelectAll(MenuItem selectAll) {
237         selectAll.setVisible(true);
238         selectAll.setEnabled(true);
239     }
240 
241     @Override
updateCreateDir(MenuItem createDir)242     protected void updateCreateDir(MenuItem createDir) {
243         createDir.setVisible(true);
244         createDir.setEnabled(mDirDetails.canCreateDirectory());
245     }
246 
247     @Override
updateShare(MenuItem share, SelectionDetails selectionDetails)248     protected void updateShare(MenuItem share, SelectionDetails selectionDetails) {
249         boolean enabled = !selectionDetails.containsDirectories()
250                 && !selectionDetails.containsPartialFiles()
251                 && !selectionDetails.canExtract();
252         share.setVisible(enabled);
253         share.setEnabled(enabled);
254     }
255 
256     @Override
updateDelete(MenuItem delete, SelectionDetails selectionDetails)257     protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
258         boolean enabled = selectionDetails.canDelete();
259         delete.setVisible(enabled);
260         delete.setEnabled(enabled);
261     }
262 
263     @Override
updateRename(MenuItem rename, SelectionDetails selectionDetails)264     protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
265         rename.setVisible(true);
266         rename.setEnabled(!selectionDetails.containsPartialFiles() && selectionDetails.canRename());
267     }
268 
269     @Override
updateInspect(MenuItem inspect)270     protected void updateInspect(MenuItem inspect) {
271         boolean visible = mFeatures.isInspectorEnabled();
272         inspect.setVisible(visible);
273         // use a null check w/ peek instead of isEmpty since
274         // DocumentStack accepts null values (not sure why).
275         inspect.setEnabled(visible && mState.stack.peek() != null);
276     }
277 
278     @Override
updateInspect(MenuItem inspect, SelectionDetails selectionDetails)279     protected void updateInspect(MenuItem inspect, SelectionDetails selectionDetails) {
280         boolean visible = mFeatures.isInspectorEnabled();
281         inspect.setVisible(visible);
282         inspect.setEnabled(visible && selectionDetails.size() <= 1);
283     }
284 
285     @Override
updateViewInOwner(MenuItem view, SelectionDetails selectionDetails)286     protected void updateViewInOwner(MenuItem view, SelectionDetails selectionDetails) {
287         if (selectionDetails.canViewInOwner()) {
288             view.setVisible(true);
289             view.setEnabled(true);
290             Resources res = mContext.getResources();
291             String selectedModelId = mSelectionManager.getSelection().iterator().next();
292             Uri selectedUri = mUriLookup.lookup(selectedModelId);
293             String appName = mAppNameLookup.lookup(selectedUri.getAuthority());
294             String title = res.getString(R.string.menu_view_in_owner, appName);
295             view.setTitle(title);
296         }
297         else {
298             view.setVisible(false);
299         }
300     }
301 }
302