blob: 5bf360fde1fa4058533a6b8f380605ad70265606 [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
Ben Lin8e912582016-09-23 14:25:14 -070025import com.android.documentsui.base.DocumentInfo;
Steve McKayd9caa6a2016-09-15 16:36:45 -070026import com.android.documentsui.base.Menus;
Steve McKayd0805062016-09-15 14:30:38 -070027import com.android.documentsui.base.RootInfo;
Steve McKayd9caa6a2016-09-15 16:36:45 -070028import com.android.documentsui.base.Shared;
29import com.android.documentsui.base.State;
Ben Lina8673232016-09-28 15:40:04 -070030import com.android.documentsui.dirlist.ActionModeController;
Garfield Tan06c4b112016-09-14 11:05:58 -070031import com.android.documentsui.dirlist.DirectoryFragment;
Garfield Tanb285b402016-09-21 17:12:18 -070032import com.android.documentsui.sidebar.RootsFragment;
Garfield Tan239ab972016-09-16 13:33:48 -070033import com.android.internal.annotations.VisibleForTesting;
Ben Lin5668b862016-06-28 17:12:52 -070034
Ben Linebf2a172016-06-03 13:46:52 -070035public abstract class MenuManager {
Ben Lin7c35b032016-05-31 13:24:01 -070036
Garfield Tan25676032016-09-19 13:52:35 -070037 final protected SearchViewManager mSearchManager;
Steve McKaye5d6ca22016-09-19 20:27:24 -070038 final protected State mState;
39 final protected DirectoryDetails mDirDetails;
Ben Lin25679912016-06-17 11:48:57 -070040
Steve McKaye5d6ca22016-09-19 20:27:24 -070041 public MenuManager(
42 SearchViewManager searchManager,
43 State displayState,
44 DirectoryDetails dirDetails) {
Ben Lin25679912016-06-17 11:48:57 -070045 mSearchManager = searchManager;
46 mState = displayState;
Steve McKaye5d6ca22016-09-19 20:27:24 -070047 mDirDetails = dirDetails;
Ben Lin25679912016-06-17 11:48:57 -070048 }
49
Garfield Tan06c4b112016-09-14 11:05:58 -070050 /** @see ActionModeController */
Ben Linebf2a172016-06-03 13:46:52 -070051 public void updateActionMenu(Menu menu, SelectionDetails selection) {
Garfield Tan06c4b112016-09-14 11:05:58 -070052 updateOpenInActionMode(menu.findItem(R.id.menu_open), selection);
Ben Linebf2a172016-06-03 13:46:52 -070053 updateDelete(menu.findItem(R.id.menu_delete), selection);
54 updateShare(menu.findItem(R.id.menu_share), selection);
55 updateRename(menu.findItem(R.id.menu_rename), selection);
Garfield Tan06c4b112016-09-14 11:05:58 -070056 updateSelectAll(menu.findItem(R.id.menu_select_all));
Ben Linebf2a172016-06-03 13:46:52 -070057 updateMoveTo(menu.findItem(R.id.menu_move_to), selection);
58 updateCopyTo(menu.findItem(R.id.menu_copy_to), selection);
Ben Lin7c35b032016-05-31 13:24:01 -070059
Ben Linebf2a172016-06-03 13:46:52 -070060 Menus.disableHiddenItems(menu);
61 }
Ben Lin7c35b032016-05-31 13:24:01 -070062
Garfield Tan06c4b112016-09-14 11:05:58 -070063 /** @see BaseActivity#onPrepareOptionsMenu */
Steve McKaye5d6ca22016-09-19 20:27:24 -070064 public void updateOptionMenu(Menu menu) {
65 updateCreateDir(menu.findItem(R.id.menu_create_dir));
66 updateSettings(menu.findItem(R.id.menu_settings));
67 updateNewWindow(menu.findItem(R.id.menu_new_window));
68 updateModePicker(menu.findItem(R.id.menu_grid), menu.findItem(R.id.menu_list));
Garfield, Tan11d23482016-08-05 09:33:29 -070069 // Sort menu item is managed by SortMenuManager
Steve McKaye5d6ca22016-09-19 20:27:24 -070070 updateAdvanced(menu.findItem(R.id.menu_advanced));
Ben Lin7c35b032016-05-31 13:24:01 -070071
Ben Linebf2a172016-06-03 13:46:52 -070072 Menus.disableHiddenItems(menu);
73 }
Ben Lin7c35b032016-05-31 13:24:01 -070074
Garfield Tan06c4b112016-09-14 11:05:58 -070075 /**
Garfield Tan239ab972016-09-16 13:33:48 -070076 * Called when we needs {@link MenuManager} to ask Android to show context menu for us.
77 * {@link MenuManager} can choose to defeat this request.
78 *
79 * {@link #inflateContextMenuForDocs} and {@link #inflateContextMenuForContainer} are called
80 * afterwards when Android asks us to provide the content of context menus, so they're not
81 * correct locations to suppress context menus.
82 */
83 public void showContextMenu(Fragment f, View v, float x, float y) {
84 // Pickers don't have any context menu at this moment.
85 }
86
Steve McKaye5d6ca22016-09-19 20:27:24 -070087 public void inflateContextMenuForContainer(Menu menu, MenuInflater inflater) {
Garfield Tan239ab972016-09-16 13:33:48 -070088 throw new UnsupportedOperationException("Pickers don't allow context menu.");
89 }
90
91 public void inflateContextMenuForDocs(
92 Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) {
93 throw new UnsupportedOperationException("Pickers don't allow context menu.");
94 }
95
96 /**
Garfield Tan06c4b112016-09-14 11:05:58 -070097 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -070098 *
Garfield Tan06c4b112016-09-14 11:05:58 -070099 * Called when user tries to generate a context menu anchored to a file when the selection
100 * doesn't contain any folder.
101 *
102 * @param selectionDetails
103 * containsFiles may return false because this may be called when user right clicks on an
104 * unselectable item in pickers
105 */
Garfield Tan239ab972016-09-16 13:33:48 -0700106 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700107 public void updateContextMenuForFiles(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700108 assert(selectionDetails != null);
109
110 MenuItem share = menu.findItem(R.id.menu_share);
111 MenuItem open = menu.findItem(R.id.menu_open);
112 MenuItem openWith = menu.findItem(R.id.menu_open_with);
113 MenuItem rename = menu.findItem(R.id.menu_rename);
114
115 updateShare(share, selectionDetails);
116 updateOpenInContextMenu(open, selectionDetails);
117 updateOpenWith(openWith, selectionDetails);
118 updateRename(rename, selectionDetails);
119
120 updateContextMenu(menu, selectionDetails);
121 }
122
123 /**
124 * @see DirectoryFragment#onCreateContextMenu
125 *
126 * Called when user tries to generate a context menu anchored to a folder when the selection
127 * doesn't contain any file.
128 *
129 * @param selectionDetails
130 * containDirectories may return false because this may be called when user right clicks on
131 * an unselectable item in pickers
132 */
Garfield Tan239ab972016-09-16 13:33:48 -0700133 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700134 public void updateContextMenuForDirs(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700135 assert(selectionDetails != null);
136
137 MenuItem openInNewWindow = menu.findItem(R.id.menu_open_in_new_window);
138 MenuItem rename = menu.findItem(R.id.menu_rename);
139 MenuItem pasteInto = menu.findItem(R.id.menu_paste_into_folder);
140
141 updateOpenInNewWindow(openInNewWindow, selectionDetails);
142 updateRename(rename, selectionDetails);
143 updatePasteInto(pasteInto, selectionDetails);
144
145 updateContextMenu(menu, selectionDetails);
146 }
147
148 /**
149 * @see DirectoryFragment#onCreateContextMenu
150 *
151 * Update shared context menu items of both files and folders context menus.
152 */
Garfield Tan239ab972016-09-16 13:33:48 -0700153 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700154 public void updateContextMenu(Menu menu, SelectionDetails selectionDetails) {
Ben Linb2dfa122016-08-11 17:42:57 -0700155 assert(selectionDetails != null);
156
157 MenuItem cut = menu.findItem(R.id.menu_cut_to_clipboard);
158 MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
Ben Linb2dfa122016-08-11 17:42:57 -0700159 MenuItem delete = menu.findItem(R.id.menu_delete);
Ben Linb2dfa122016-08-11 17:42:57 -0700160
Garfield Tan06c4b112016-09-14 11:05:58 -0700161 final boolean canCopy =
162 selectionDetails.size() > 0 && !selectionDetails.containsPartialFiles();
163 final boolean canDelete = selectionDetails.canDelete();
164 cut.setEnabled(canCopy && canDelete);
165 copy.setEnabled(canCopy);
166 delete.setEnabled(canDelete);
Ben Linb2dfa122016-08-11 17:42:57 -0700167 }
168
Garfield Tan06c4b112016-09-14 11:05:58 -0700169 /**
170 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -0700171 *
172 * Called when user tries to generate a context menu anchored to an empty pane.
Garfield Tan06c4b112016-09-14 11:05:58 -0700173 */
Garfield Tan239ab972016-09-16 13:33:48 -0700174 @VisibleForTesting
Steve McKaye5d6ca22016-09-19 20:27:24 -0700175 public void updateContextMenuForContainer(Menu menu) {
Ben Linebf2a172016-06-03 13:46:52 -0700176 MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
Garfield Tan06c4b112016-09-14 11:05:58 -0700177 MenuItem selectAll = menu.findItem(R.id.menu_select_all);
Ben Lin7c35b032016-05-31 13:24:01 -0700178
Steve McKaye5d6ca22016-09-19 20:27:24 -0700179 paste.setEnabled(mDirDetails.hasItemsToPaste() && mDirDetails.canCreateDoc());
Garfield Tan06c4b112016-09-14 11:05:58 -0700180 updateSelectAll(selectAll);
Ben Linebf2a172016-06-03 13:46:52 -0700181 }
Ben Lin7c35b032016-05-31 13:24:01 -0700182
Garfield Tan06c4b112016-09-14 11:05:58 -0700183 /**
184 * @see RootsFragment#onCreateContextMenu
185 */
Ben Lin8e912582016-09-23 14:25:14 -0700186 public void updateRootContextMenu(Menu menu, RootInfo root, DocumentInfo docInfo) {
Ben Lin5668b862016-06-28 17:12:52 -0700187 MenuItem eject = menu.findItem(R.id.menu_eject_root);
Garfield Tanb285b402016-09-21 17:12:18 -0700188 MenuItem pasteInto = menu.findItem(R.id.menu_paste_into_folder);
189 MenuItem openInNewWindow = menu.findItem(R.id.menu_open_in_new_window);
190 MenuItem settings = menu.findItem(R.id.menu_settings);
Ben Lin5668b862016-06-28 17:12:52 -0700191
Ben Lin5668b862016-06-28 17:12:52 -0700192 updateEject(eject, root);
Ben Lin8e912582016-09-23 14:25:14 -0700193 updatePasteInto(pasteInto, root, docInfo);
Garfield Tanb285b402016-09-21 17:12:18 -0700194 updateOpenInNewWindow(openInNewWindow, root);
195 updateSettings(settings, root);
Ben Lin5668b862016-06-28 17:12:52 -0700196 }
197
Steve McKaye5d6ca22016-09-19 20:27:24 -0700198 protected void updateModePicker(MenuItem grid, MenuItem list) {
Ben Lin25679912016-06-17 11:48:57 -0700199 grid.setVisible(mState.derivedMode != State.MODE_GRID);
200 list.setVisible(mState.derivedMode != State.MODE_LIST);
201 }
202
Steve McKaye5d6ca22016-09-19 20:27:24 -0700203 protected void updateAdvanced(MenuItem advanced) {
Ben Lin25679912016-06-17 11:48:57 -0700204 advanced.setVisible(mState.showAdvancedOption);
205 advanced.setTitle(mState.showAdvancedOption && mState.showAdvanced
206 ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
207 }
208
Steve McKaye5d6ca22016-09-19 20:27:24 -0700209 protected void updateSettings(MenuItem settings) {
Ben Lin25679912016-06-17 11:48:57 -0700210 settings.setVisible(false);
211 }
212
Garfield Tan25676032016-09-19 13:52:35 -0700213 protected void updateSettings(MenuItem settings, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700214 settings.setVisible(false);
215 }
216
Garfield Tan25676032016-09-19 13:52:35 -0700217 protected void updateEject(MenuItem eject, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700218 eject.setVisible(false);
219 }
220
Steve McKaye5d6ca22016-09-19 20:27:24 -0700221 protected void updateNewWindow(MenuItem newWindow) {
Ben Lin25679912016-06-17 11:48:57 -0700222 newWindow.setVisible(false);
223 }
224
Garfield Tan25676032016-09-19 13:52:35 -0700225 protected void updateOpenInActionMode(MenuItem open, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700226 open.setVisible(false);
227 }
228
Garfield Tan25676032016-09-19 13:52:35 -0700229 protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700230 openWith.setVisible(false);
231 }
232
Garfield Tan25676032016-09-19 13:52:35 -0700233 protected void updateOpenInNewWindow(
234 MenuItem openInNewWindow, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700235 openInNewWindow.setVisible(false);
236 }
237
Garfield Tanb285b402016-09-21 17:12:18 -0700238 protected void updateOpenInNewWindow(
239 MenuItem openInNewWindow, RootInfo root) {
240 openInNewWindow.setVisible(false);
241 }
242
Garfield Tan25676032016-09-19 13:52:35 -0700243 protected void updateShare(MenuItem share, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700244 share.setVisible(false);
245 }
246
Garfield Tan25676032016-09-19 13:52:35 -0700247 protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700248 delete.setVisible(false);
249 }
250
Garfield Tan25676032016-09-19 13:52:35 -0700251 protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700252 rename.setVisible(false);
253 }
254
Garfield Tan25676032016-09-19 13:52:35 -0700255 protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700256 moveTo.setVisible(false);
257 }
258
Garfield Tan25676032016-09-19 13:52:35 -0700259 protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700260 copyTo.setVisible(false);
261 }
262
Garfield Tan25676032016-09-19 13:52:35 -0700263 protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700264 pasteInto.setVisible(false);
Ben Linb2dfa122016-08-11 17:42:57 -0700265 }
266
Ben Lin8e912582016-09-23 14:25:14 -0700267 protected void updatePasteInto(MenuItem pasteInto, RootInfo root, DocumentInfo docInfo) {
Garfield Tanb285b402016-09-21 17:12:18 -0700268 pasteInto.setVisible(false);
269 }
270
Garfield Tan25676032016-09-19 13:52:35 -0700271 protected abstract void updateOpenInContextMenu(
272 MenuItem open, SelectionDetails selectionDetails);
273 protected abstract void updateSelectAll(MenuItem selectAll);
Steve McKaye5d6ca22016-09-19 20:27:24 -0700274 protected abstract void updateCreateDir(MenuItem createDir);
Ben Lin7c35b032016-05-31 13:24:01 -0700275
Ben Linebf2a172016-06-03 13:46:52 -0700276 /**
277 * Access to meta data about the selection.
278 */
279 public interface SelectionDetails {
280 boolean containsDirectories();
281
Garfield Tan06c4b112016-09-14 11:05:58 -0700282 boolean containsFiles();
283
284 int size();
285
Ben Linebf2a172016-06-03 13:46:52 -0700286 boolean containsPartialFiles();
287
288 // TODO: Update these to express characteristics instead of answering concrete questions,
289 // since the answer to those questions is (or can be) activity specific.
290 boolean canDelete();
291
292 boolean canRename();
Ben Linb2dfa122016-08-11 17:42:57 -0700293
294 boolean canPasteInto();
Ben Linebf2a172016-06-03 13:46:52 -0700295 }
296
297 public static class DirectoryDetails {
298 private final BaseActivity mActivity;
299
300 public DirectoryDetails(BaseActivity activity) {
301 mActivity = activity;
302 }
303
304 public boolean shouldShowFancyFeatures() {
305 return Shared.shouldShowFancyFeatures(mActivity);
306 }
307
308 public boolean hasRootSettings() {
309 return mActivity.getCurrentRoot().hasSettings();
310 }
311
312 public boolean hasItemsToPaste() {
313 return false;
314 }
315
Garfield Tan06c4b112016-09-14 11:05:58 -0700316 public boolean canCreateDoc() {
317 return isInRecents() ? false : mActivity.getCurrentDirectory().isCreateSupported();
318 }
319
Ben Linebf2a172016-06-03 13:46:52 -0700320 public boolean isInRecents() {
321 return mActivity.getCurrentDirectory() == null;
322 }
323
324 public boolean canCreateDirectory() {
325 return mActivity.canCreateDirectory();
326 }
327 }
328}