blob: 55dffb1cc9bc39ee60c1518cb5e2a9685d4ff5b7 [file] [log] [blame]
Ben Lin7c35b032016-05-31 13:24:01 -07001/*
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
17package com.android.documentsui;
18
Garfield Tan239ab972016-09-16 13:33:48 -070019import android.app.Fragment;
Ben Lin7c35b032016-05-31 13:24:01 -070020import android.view.Menu;
Garfield Tan239ab972016-09-16 13:33:48 -070021import android.view.MenuInflater;
Ben Linebf2a172016-06-03 13:46:52 -070022import android.view.MenuItem;
Garfield Tan239ab972016-09-16 13:33:48 -070023import android.view.View;
Ben Lin7c35b032016-05-31 13:24:01 -070024
Steve McKayd9caa6a2016-09-15 16:36:45 -070025import com.android.documentsui.base.Menus;
Steve McKayd0805062016-09-15 14:30:38 -070026import com.android.documentsui.base.RootInfo;
Steve McKayd9caa6a2016-09-15 16:36:45 -070027import com.android.documentsui.base.Shared;
28import com.android.documentsui.base.State;
Garfield Tan06c4b112016-09-14 11:05:58 -070029import com.android.documentsui.dirlist.DirectoryFragment;
Garfield Tan239ab972016-09-16 13:33:48 -070030import com.android.internal.annotations.VisibleForTesting;
Ben Lin5668b862016-06-28 17:12:52 -070031
Ben Linebf2a172016-06-03 13:46:52 -070032public abstract class MenuManager {
Ben Lin7c35b032016-05-31 13:24:01 -070033
Garfield Tan25676032016-09-19 13:52:35 -070034 final protected State mState;
35 final protected SearchViewManager mSearchManager;
Ben Lin25679912016-06-17 11:48:57 -070036
37 public MenuManager(SearchViewManager searchManager, State displayState) {
38 mSearchManager = searchManager;
39 mState = displayState;
40 }
41
Garfield Tan06c4b112016-09-14 11:05:58 -070042 /** @see ActionModeController */
Ben Linebf2a172016-06-03 13:46:52 -070043 public void updateActionMenu(Menu menu, SelectionDetails selection) {
Garfield Tan06c4b112016-09-14 11:05:58 -070044 updateOpenInActionMode(menu.findItem(R.id.menu_open), selection);
Ben Linebf2a172016-06-03 13:46:52 -070045 updateDelete(menu.findItem(R.id.menu_delete), selection);
46 updateShare(menu.findItem(R.id.menu_share), selection);
47 updateRename(menu.findItem(R.id.menu_rename), selection);
Garfield Tan06c4b112016-09-14 11:05:58 -070048 updateSelectAll(menu.findItem(R.id.menu_select_all));
Ben Linebf2a172016-06-03 13:46:52 -070049 updateMoveTo(menu.findItem(R.id.menu_move_to), selection);
50 updateCopyTo(menu.findItem(R.id.menu_copy_to), selection);
Ben Lin7c35b032016-05-31 13:24:01 -070051
Ben Linebf2a172016-06-03 13:46:52 -070052 Menus.disableHiddenItems(menu);
53 }
Ben Lin7c35b032016-05-31 13:24:01 -070054
Garfield Tan06c4b112016-09-14 11:05:58 -070055 /** @see BaseActivity#onPrepareOptionsMenu */
Ben Lin25679912016-06-17 11:48:57 -070056 public void updateOptionMenu(Menu menu, DirectoryDetails directoryDetails) {
57 updateCreateDir(menu.findItem(R.id.menu_create_dir), directoryDetails);
58 updateSettings(menu.findItem(R.id.menu_settings), directoryDetails);
59 updateNewWindow(menu.findItem(R.id.menu_new_window), directoryDetails);
Ben Lin25679912016-06-17 11:48:57 -070060 updateModePicker(menu.findItem(
61 R.id.menu_grid), menu.findItem(R.id.menu_list), directoryDetails);
Garfield, Tan11d23482016-08-05 09:33:29 -070062 // Sort menu item is managed by SortMenuManager
Ben Lin25679912016-06-17 11:48:57 -070063 updateAdvanced(menu.findItem(R.id.menu_advanced), directoryDetails);
Ben Lin7c35b032016-05-31 13:24:01 -070064
Ben Linebf2a172016-06-03 13:46:52 -070065 Menus.disableHiddenItems(menu);
66 }
Ben Lin7c35b032016-05-31 13:24:01 -070067
Garfield Tan06c4b112016-09-14 11:05:58 -070068 /**
Garfield Tan239ab972016-09-16 13:33:48 -070069 * Called when we needs {@link MenuManager} to ask Android to show context menu for us.
70 * {@link MenuManager} can choose to defeat this request.
71 *
72 * {@link #inflateContextMenuForDocs} and {@link #inflateContextMenuForContainer} are called
73 * afterwards when Android asks us to provide the content of context menus, so they're not
74 * correct locations to suppress context menus.
75 */
76 public void showContextMenu(Fragment f, View v, float x, float y) {
77 // Pickers don't have any context menu at this moment.
78 }
79
80 public void inflateContextMenuForContainer(
81 Menu menu, MenuInflater inflater, DirectoryDetails directoryDetails) {
82 throw new UnsupportedOperationException("Pickers don't allow context menu.");
83 }
84
85 public void inflateContextMenuForDocs(
86 Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) {
87 throw new UnsupportedOperationException("Pickers don't allow context menu.");
88 }
89
90 /**
Garfield Tan06c4b112016-09-14 11:05:58 -070091 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -070092 *
Garfield Tan06c4b112016-09-14 11:05:58 -070093 * Called when user tries to generate a context menu anchored to a file when the selection
94 * doesn't contain any folder.
95 *
96 * @param selectionDetails
97 * containsFiles may return false because this may be called when user right clicks on an
98 * unselectable item in pickers
99 */
Garfield Tan239ab972016-09-16 13:33:48 -0700100 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700101 public void updateContextMenuForFiles(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700102 assert(selectionDetails != null);
103
104 MenuItem share = menu.findItem(R.id.menu_share);
105 MenuItem open = menu.findItem(R.id.menu_open);
106 MenuItem openWith = menu.findItem(R.id.menu_open_with);
107 MenuItem rename = menu.findItem(R.id.menu_rename);
108
109 updateShare(share, selectionDetails);
110 updateOpenInContextMenu(open, selectionDetails);
111 updateOpenWith(openWith, selectionDetails);
112 updateRename(rename, selectionDetails);
113
114 updateContextMenu(menu, selectionDetails);
115 }
116
117 /**
118 * @see DirectoryFragment#onCreateContextMenu
119 *
120 * Called when user tries to generate a context menu anchored to a folder when the selection
121 * doesn't contain any file.
122 *
123 * @param selectionDetails
124 * containDirectories may return false because this may be called when user right clicks on
125 * an unselectable item in pickers
126 */
Garfield Tan239ab972016-09-16 13:33:48 -0700127 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700128 public void updateContextMenuForDirs(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700129 assert(selectionDetails != null);
130
131 MenuItem openInNewWindow = menu.findItem(R.id.menu_open_in_new_window);
132 MenuItem rename = menu.findItem(R.id.menu_rename);
133 MenuItem pasteInto = menu.findItem(R.id.menu_paste_into_folder);
134
135 updateOpenInNewWindow(openInNewWindow, selectionDetails);
136 updateRename(rename, selectionDetails);
137 updatePasteInto(pasteInto, selectionDetails);
138
139 updateContextMenu(menu, selectionDetails);
140 }
141
142 /**
143 * @see DirectoryFragment#onCreateContextMenu
144 *
145 * Update shared context menu items of both files and folders context menus.
146 */
Garfield Tan239ab972016-09-16 13:33:48 -0700147 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700148 public void updateContextMenu(Menu menu, SelectionDetails selectionDetails) {
Ben Linb2dfa122016-08-11 17:42:57 -0700149 assert(selectionDetails != null);
150
151 MenuItem cut = menu.findItem(R.id.menu_cut_to_clipboard);
152 MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
Ben Linb2dfa122016-08-11 17:42:57 -0700153 MenuItem delete = menu.findItem(R.id.menu_delete);
Ben Linb2dfa122016-08-11 17:42:57 -0700154
Garfield Tan06c4b112016-09-14 11:05:58 -0700155 final boolean canCopy =
156 selectionDetails.size() > 0 && !selectionDetails.containsPartialFiles();
157 final boolean canDelete = selectionDetails.canDelete();
158 cut.setEnabled(canCopy && canDelete);
159 copy.setEnabled(canCopy);
160 delete.setEnabled(canDelete);
Ben Linb2dfa122016-08-11 17:42:57 -0700161 }
162
Garfield Tan06c4b112016-09-14 11:05:58 -0700163 /**
164 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -0700165 *
166 * Called when user tries to generate a context menu anchored to an empty pane.
Garfield Tan06c4b112016-09-14 11:05:58 -0700167 */
Garfield Tan239ab972016-09-16 13:33:48 -0700168 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700169 public void updateContextMenuForContainer(Menu menu, DirectoryDetails directoryDetails) {
Ben Linebf2a172016-06-03 13:46:52 -0700170 MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
Garfield Tan06c4b112016-09-14 11:05:58 -0700171 MenuItem selectAll = menu.findItem(R.id.menu_select_all);
Ben Lin7c35b032016-05-31 13:24:01 -0700172
Garfield Tan06c4b112016-09-14 11:05:58 -0700173 paste.setEnabled(directoryDetails.hasItemsToPaste() && directoryDetails.canCreateDoc());
174 updateSelectAll(selectAll);
Ben Linebf2a172016-06-03 13:46:52 -0700175 }
Ben Lin7c35b032016-05-31 13:24:01 -0700176
Garfield Tan06c4b112016-09-14 11:05:58 -0700177 /**
178 * @see RootsFragment#onCreateContextMenu
179 */
Ben Lin5668b862016-06-28 17:12:52 -0700180 public void updateRootContextMenu(Menu menu, RootInfo root) {
181 MenuItem settings = menu.findItem(R.id.menu_settings);
182 MenuItem eject = menu.findItem(R.id.menu_eject_root);
183
184 updateSettings(settings, root);
185 updateEject(eject, root);
186 }
187
Garfield Tan25676032016-09-19 13:52:35 -0700188 protected void updateModePicker(
189 MenuItem grid, MenuItem list, DirectoryDetails directoryDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700190 grid.setVisible(mState.derivedMode != State.MODE_GRID);
191 list.setVisible(mState.derivedMode != State.MODE_LIST);
192 }
193
Garfield Tan25676032016-09-19 13:52:35 -0700194 protected void updateAdvanced(MenuItem advanced, DirectoryDetails directoryDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700195 advanced.setVisible(mState.showAdvancedOption);
196 advanced.setTitle(mState.showAdvancedOption && mState.showAdvanced
197 ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
198 }
199
Garfield Tan25676032016-09-19 13:52:35 -0700200 protected void updateSettings(MenuItem settings, DirectoryDetails directoryDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700201 settings.setVisible(false);
202 }
203
Garfield Tan25676032016-09-19 13:52:35 -0700204 protected void updateSettings(MenuItem settings, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700205 settings.setVisible(false);
206 }
207
Garfield Tan25676032016-09-19 13:52:35 -0700208 protected void updateEject(MenuItem eject, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700209 eject.setVisible(false);
210 }
211
Garfield Tan25676032016-09-19 13:52:35 -0700212 protected void updateNewWindow(MenuItem newWindow, DirectoryDetails directoryDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700213 newWindow.setVisible(false);
214 }
215
Garfield Tan25676032016-09-19 13:52:35 -0700216 protected void updateOpenInActionMode(MenuItem open, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700217 open.setVisible(false);
218 }
219
Garfield Tan25676032016-09-19 13:52:35 -0700220 protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700221 openWith.setVisible(false);
222 }
223
Garfield Tan25676032016-09-19 13:52:35 -0700224 protected void updateOpenInNewWindow(
225 MenuItem openInNewWindow, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700226 openInNewWindow.setVisible(false);
227 }
228
Garfield Tan25676032016-09-19 13:52:35 -0700229 protected void updateShare(MenuItem share, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700230 share.setVisible(false);
231 }
232
Garfield Tan25676032016-09-19 13:52:35 -0700233 protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700234 delete.setVisible(false);
235 }
236
Garfield Tan25676032016-09-19 13:52:35 -0700237 protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700238 rename.setVisible(false);
239 }
240
Garfield Tan25676032016-09-19 13:52:35 -0700241 protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700242 moveTo.setVisible(false);
243 }
244
Garfield Tan25676032016-09-19 13:52:35 -0700245 protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700246 copyTo.setVisible(false);
247 }
248
Garfield Tan25676032016-09-19 13:52:35 -0700249 protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700250 pasteInto.setVisible(false);
Ben Linb2dfa122016-08-11 17:42:57 -0700251 }
252
Garfield Tan25676032016-09-19 13:52:35 -0700253 protected abstract void updateOpenInContextMenu(
254 MenuItem open, SelectionDetails selectionDetails);
255 protected abstract void updateSelectAll(MenuItem selectAll);
256 protected abstract void updateCreateDir(MenuItem createDir, DirectoryDetails directoryDetails);
Ben Lin7c35b032016-05-31 13:24:01 -0700257
Ben Linebf2a172016-06-03 13:46:52 -0700258 /**
259 * Access to meta data about the selection.
260 */
261 public interface SelectionDetails {
262 boolean containsDirectories();
263
Garfield Tan06c4b112016-09-14 11:05:58 -0700264 boolean containsFiles();
265
266 int size();
267
Ben Linebf2a172016-06-03 13:46:52 -0700268 boolean containsPartialFiles();
269
270 // TODO: Update these to express characteristics instead of answering concrete questions,
271 // since the answer to those questions is (or can be) activity specific.
272 boolean canDelete();
273
274 boolean canRename();
Ben Linb2dfa122016-08-11 17:42:57 -0700275
276 boolean canPasteInto();
Ben Linebf2a172016-06-03 13:46:52 -0700277 }
278
279 public static class DirectoryDetails {
280 private final BaseActivity mActivity;
281
282 public DirectoryDetails(BaseActivity activity) {
283 mActivity = activity;
284 }
285
286 public boolean shouldShowFancyFeatures() {
287 return Shared.shouldShowFancyFeatures(mActivity);
288 }
289
290 public boolean hasRootSettings() {
291 return mActivity.getCurrentRoot().hasSettings();
292 }
293
294 public boolean hasItemsToPaste() {
295 return false;
296 }
297
Garfield Tan06c4b112016-09-14 11:05:58 -0700298 public boolean canCreateDoc() {
299 return isInRecents() ? false : mActivity.getCurrentDirectory().isCreateSupported();
300 }
301
Ben Linebf2a172016-06-03 13:46:52 -0700302 public boolean isInRecents() {
303 return mActivity.getCurrentDirectory() == null;
304 }
305
306 public boolean canCreateDirectory() {
307 return mActivity.canCreateDirectory();
308 }
309 }
310}