blob: 56f4214aefdb9b01e31d2c322046cfe7596abaa4 [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 Tanb285b402016-09-21 17:12:18 -070030import com.android.documentsui.sidebar.RootsFragment;
Garfield Tan239ab972016-09-16 13:33:48 -070031import com.android.internal.annotations.VisibleForTesting;
Ben Lin5668b862016-06-28 17:12:52 -070032
Ben Linebf2a172016-06-03 13:46:52 -070033public abstract class MenuManager {
Ben Lin7c35b032016-05-31 13:24:01 -070034
Garfield Tan25676032016-09-19 13:52:35 -070035 final protected SearchViewManager mSearchManager;
Steve McKaye5d6ca22016-09-19 20:27:24 -070036 final protected State mState;
37 final protected DirectoryDetails mDirDetails;
Ben Lin25679912016-06-17 11:48:57 -070038
Steve McKaye5d6ca22016-09-19 20:27:24 -070039 public MenuManager(
40 SearchViewManager searchManager,
41 State displayState,
42 DirectoryDetails dirDetails) {
Ben Lin25679912016-06-17 11:48:57 -070043 mSearchManager = searchManager;
44 mState = displayState;
Steve McKaye5d6ca22016-09-19 20:27:24 -070045 mDirDetails = dirDetails;
Ben Lin25679912016-06-17 11:48:57 -070046 }
47
Garfield Tan06c4b112016-09-14 11:05:58 -070048 /** @see ActionModeController */
Ben Linebf2a172016-06-03 13:46:52 -070049 public void updateActionMenu(Menu menu, SelectionDetails selection) {
Garfield Tan06c4b112016-09-14 11:05:58 -070050 updateOpenInActionMode(menu.findItem(R.id.menu_open), selection);
Ben Linebf2a172016-06-03 13:46:52 -070051 updateDelete(menu.findItem(R.id.menu_delete), selection);
52 updateShare(menu.findItem(R.id.menu_share), selection);
53 updateRename(menu.findItem(R.id.menu_rename), selection);
Garfield Tan06c4b112016-09-14 11:05:58 -070054 updateSelectAll(menu.findItem(R.id.menu_select_all));
Ben Linebf2a172016-06-03 13:46:52 -070055 updateMoveTo(menu.findItem(R.id.menu_move_to), selection);
56 updateCopyTo(menu.findItem(R.id.menu_copy_to), selection);
Ben Lin7c35b032016-05-31 13:24:01 -070057
Ben Linebf2a172016-06-03 13:46:52 -070058 Menus.disableHiddenItems(menu);
59 }
Ben Lin7c35b032016-05-31 13:24:01 -070060
Garfield Tan06c4b112016-09-14 11:05:58 -070061 /** @see BaseActivity#onPrepareOptionsMenu */
Steve McKaye5d6ca22016-09-19 20:27:24 -070062 public void updateOptionMenu(Menu menu) {
63 updateCreateDir(menu.findItem(R.id.menu_create_dir));
64 updateSettings(menu.findItem(R.id.menu_settings));
65 updateNewWindow(menu.findItem(R.id.menu_new_window));
66 updateModePicker(menu.findItem(R.id.menu_grid), menu.findItem(R.id.menu_list));
Garfield, Tan11d23482016-08-05 09:33:29 -070067 // Sort menu item is managed by SortMenuManager
Steve McKaye5d6ca22016-09-19 20:27:24 -070068 updateAdvanced(menu.findItem(R.id.menu_advanced));
Ben Lin7c35b032016-05-31 13:24:01 -070069
Ben Linebf2a172016-06-03 13:46:52 -070070 Menus.disableHiddenItems(menu);
71 }
Ben Lin7c35b032016-05-31 13:24:01 -070072
Garfield Tan06c4b112016-09-14 11:05:58 -070073 /**
Garfield Tan239ab972016-09-16 13:33:48 -070074 * Called when we needs {@link MenuManager} to ask Android to show context menu for us.
75 * {@link MenuManager} can choose to defeat this request.
76 *
77 * {@link #inflateContextMenuForDocs} and {@link #inflateContextMenuForContainer} are called
78 * afterwards when Android asks us to provide the content of context menus, so they're not
79 * correct locations to suppress context menus.
80 */
81 public void showContextMenu(Fragment f, View v, float x, float y) {
82 // Pickers don't have any context menu at this moment.
83 }
84
Steve McKaye5d6ca22016-09-19 20:27:24 -070085 public void inflateContextMenuForContainer(Menu menu, MenuInflater inflater) {
Garfield Tan239ab972016-09-16 13:33:48 -070086 throw new UnsupportedOperationException("Pickers don't allow context menu.");
87 }
88
89 public void inflateContextMenuForDocs(
90 Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) {
91 throw new UnsupportedOperationException("Pickers don't allow context menu.");
92 }
93
94 /**
Garfield Tan06c4b112016-09-14 11:05:58 -070095 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -070096 *
Garfield Tan06c4b112016-09-14 11:05:58 -070097 * Called when user tries to generate a context menu anchored to a file when the selection
98 * doesn't contain any folder.
99 *
100 * @param selectionDetails
101 * containsFiles may return false because this may be called when user right clicks on an
102 * unselectable item in pickers
103 */
Garfield Tan239ab972016-09-16 13:33:48 -0700104 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700105 public void updateContextMenuForFiles(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700106 assert(selectionDetails != null);
107
108 MenuItem share = menu.findItem(R.id.menu_share);
109 MenuItem open = menu.findItem(R.id.menu_open);
110 MenuItem openWith = menu.findItem(R.id.menu_open_with);
111 MenuItem rename = menu.findItem(R.id.menu_rename);
112
113 updateShare(share, selectionDetails);
114 updateOpenInContextMenu(open, selectionDetails);
115 updateOpenWith(openWith, selectionDetails);
116 updateRename(rename, selectionDetails);
117
118 updateContextMenu(menu, selectionDetails);
119 }
120
121 /**
122 * @see DirectoryFragment#onCreateContextMenu
123 *
124 * Called when user tries to generate a context menu anchored to a folder when the selection
125 * doesn't contain any file.
126 *
127 * @param selectionDetails
128 * containDirectories may return false because this may be called when user right clicks on
129 * an unselectable item in pickers
130 */
Garfield Tan239ab972016-09-16 13:33:48 -0700131 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700132 public void updateContextMenuForDirs(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700133 assert(selectionDetails != null);
134
135 MenuItem openInNewWindow = menu.findItem(R.id.menu_open_in_new_window);
136 MenuItem rename = menu.findItem(R.id.menu_rename);
137 MenuItem pasteInto = menu.findItem(R.id.menu_paste_into_folder);
138
139 updateOpenInNewWindow(openInNewWindow, selectionDetails);
140 updateRename(rename, selectionDetails);
141 updatePasteInto(pasteInto, selectionDetails);
142
143 updateContextMenu(menu, selectionDetails);
144 }
145
146 /**
147 * @see DirectoryFragment#onCreateContextMenu
148 *
149 * Update shared context menu items of both files and folders context menus.
150 */
Garfield Tan239ab972016-09-16 13:33:48 -0700151 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700152 public void updateContextMenu(Menu menu, SelectionDetails selectionDetails) {
Ben Linb2dfa122016-08-11 17:42:57 -0700153 assert(selectionDetails != null);
154
155 MenuItem cut = menu.findItem(R.id.menu_cut_to_clipboard);
156 MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
Ben Linb2dfa122016-08-11 17:42:57 -0700157 MenuItem delete = menu.findItem(R.id.menu_delete);
Ben Linb2dfa122016-08-11 17:42:57 -0700158
Garfield Tan06c4b112016-09-14 11:05:58 -0700159 final boolean canCopy =
160 selectionDetails.size() > 0 && !selectionDetails.containsPartialFiles();
161 final boolean canDelete = selectionDetails.canDelete();
162 cut.setEnabled(canCopy && canDelete);
163 copy.setEnabled(canCopy);
164 delete.setEnabled(canDelete);
Ben Linb2dfa122016-08-11 17:42:57 -0700165 }
166
Garfield Tan06c4b112016-09-14 11:05:58 -0700167 /**
168 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -0700169 *
170 * Called when user tries to generate a context menu anchored to an empty pane.
Garfield Tan06c4b112016-09-14 11:05:58 -0700171 */
Garfield Tan239ab972016-09-16 13:33:48 -0700172 @VisibleForTesting
Steve McKaye5d6ca22016-09-19 20:27:24 -0700173 public void updateContextMenuForContainer(Menu menu) {
Ben Linebf2a172016-06-03 13:46:52 -0700174 MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
Garfield Tan06c4b112016-09-14 11:05:58 -0700175 MenuItem selectAll = menu.findItem(R.id.menu_select_all);
Ben Lin7c35b032016-05-31 13:24:01 -0700176
Steve McKaye5d6ca22016-09-19 20:27:24 -0700177 paste.setEnabled(mDirDetails.hasItemsToPaste() && mDirDetails.canCreateDoc());
Garfield Tan06c4b112016-09-14 11:05:58 -0700178 updateSelectAll(selectAll);
Ben Linebf2a172016-06-03 13:46:52 -0700179 }
Ben Lin7c35b032016-05-31 13:24:01 -0700180
Garfield Tan06c4b112016-09-14 11:05:58 -0700181 /**
182 * @see RootsFragment#onCreateContextMenu
183 */
Ben Lin5668b862016-06-28 17:12:52 -0700184 public void updateRootContextMenu(Menu menu, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700185 MenuItem eject = menu.findItem(R.id.menu_eject_root);
Garfield Tanb285b402016-09-21 17:12:18 -0700186 MenuItem pasteInto = menu.findItem(R.id.menu_paste_into_folder);
187 MenuItem openInNewWindow = menu.findItem(R.id.menu_open_in_new_window);
188 MenuItem settings = menu.findItem(R.id.menu_settings);
Ben Lin5668b862016-06-28 17:12:52 -0700189
Ben Lin5668b862016-06-28 17:12:52 -0700190 updateEject(eject, root);
Garfield Tanb285b402016-09-21 17:12:18 -0700191 updatePasteInto(pasteInto, root);
192 updateOpenInNewWindow(openInNewWindow, root);
193 updateSettings(settings, root);
Ben Lin5668b862016-06-28 17:12:52 -0700194 }
195
Steve McKaye5d6ca22016-09-19 20:27:24 -0700196 protected void updateModePicker(MenuItem grid, MenuItem list) {
Ben Lin25679912016-06-17 11:48:57 -0700197 grid.setVisible(mState.derivedMode != State.MODE_GRID);
198 list.setVisible(mState.derivedMode != State.MODE_LIST);
199 }
200
Steve McKaye5d6ca22016-09-19 20:27:24 -0700201 protected void updateAdvanced(MenuItem advanced) {
Ben Lin25679912016-06-17 11:48:57 -0700202 advanced.setVisible(mState.showAdvancedOption);
203 advanced.setTitle(mState.showAdvancedOption && mState.showAdvanced
204 ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
205 }
206
Steve McKaye5d6ca22016-09-19 20:27:24 -0700207 protected void updateSettings(MenuItem settings) {
Ben Lin25679912016-06-17 11:48:57 -0700208 settings.setVisible(false);
209 }
210
Garfield Tan25676032016-09-19 13:52:35 -0700211 protected void updateSettings(MenuItem settings, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700212 settings.setVisible(false);
213 }
214
Garfield Tan25676032016-09-19 13:52:35 -0700215 protected void updateEject(MenuItem eject, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700216 eject.setVisible(false);
217 }
218
Steve McKaye5d6ca22016-09-19 20:27:24 -0700219 protected void updateNewWindow(MenuItem newWindow) {
Ben Lin25679912016-06-17 11:48:57 -0700220 newWindow.setVisible(false);
221 }
222
Garfield Tan25676032016-09-19 13:52:35 -0700223 protected void updateOpenInActionMode(MenuItem open, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700224 open.setVisible(false);
225 }
226
Garfield Tan25676032016-09-19 13:52:35 -0700227 protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700228 openWith.setVisible(false);
229 }
230
Garfield Tan25676032016-09-19 13:52:35 -0700231 protected void updateOpenInNewWindow(
232 MenuItem openInNewWindow, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700233 openInNewWindow.setVisible(false);
234 }
235
Garfield Tanb285b402016-09-21 17:12:18 -0700236 protected void updateOpenInNewWindow(
237 MenuItem openInNewWindow, RootInfo root) {
238 openInNewWindow.setVisible(false);
239 }
240
Garfield Tan25676032016-09-19 13:52:35 -0700241 protected void updateShare(MenuItem share, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700242 share.setVisible(false);
243 }
244
Garfield Tan25676032016-09-19 13:52:35 -0700245 protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700246 delete.setVisible(false);
247 }
248
Garfield Tan25676032016-09-19 13:52:35 -0700249 protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700250 rename.setVisible(false);
251 }
252
Garfield Tan25676032016-09-19 13:52:35 -0700253 protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700254 moveTo.setVisible(false);
255 }
256
Garfield Tan25676032016-09-19 13:52:35 -0700257 protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700258 copyTo.setVisible(false);
259 }
260
Garfield Tan25676032016-09-19 13:52:35 -0700261 protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700262 pasteInto.setVisible(false);
Ben Linb2dfa122016-08-11 17:42:57 -0700263 }
264
Garfield Tanb285b402016-09-21 17:12:18 -0700265 protected void updatePasteInto(MenuItem pasteInto, RootInfo root) {
266 pasteInto.setVisible(false);
267 }
268
Garfield Tan25676032016-09-19 13:52:35 -0700269 protected abstract void updateOpenInContextMenu(
270 MenuItem open, SelectionDetails selectionDetails);
271 protected abstract void updateSelectAll(MenuItem selectAll);
Steve McKaye5d6ca22016-09-19 20:27:24 -0700272 protected abstract void updateCreateDir(MenuItem createDir);
Ben Lin7c35b032016-05-31 13:24:01 -0700273
Ben Linebf2a172016-06-03 13:46:52 -0700274 /**
275 * Access to meta data about the selection.
276 */
277 public interface SelectionDetails {
278 boolean containsDirectories();
279
Garfield Tan06c4b112016-09-14 11:05:58 -0700280 boolean containsFiles();
281
282 int size();
283
Ben Linebf2a172016-06-03 13:46:52 -0700284 boolean containsPartialFiles();
285
286 // TODO: Update these to express characteristics instead of answering concrete questions,
287 // since the answer to those questions is (or can be) activity specific.
288 boolean canDelete();
289
290 boolean canRename();
Ben Linb2dfa122016-08-11 17:42:57 -0700291
292 boolean canPasteInto();
Ben Linebf2a172016-06-03 13:46:52 -0700293 }
294
295 public static class DirectoryDetails {
296 private final BaseActivity mActivity;
297
298 public DirectoryDetails(BaseActivity activity) {
299 mActivity = activity;
300 }
301
302 public boolean shouldShowFancyFeatures() {
303 return Shared.shouldShowFancyFeatures(mActivity);
304 }
305
306 public boolean hasRootSettings() {
307 return mActivity.getCurrentRoot().hasSettings();
308 }
309
310 public boolean hasItemsToPaste() {
311 return false;
312 }
313
Garfield Tan06c4b112016-09-14 11:05:58 -0700314 public boolean canCreateDoc() {
315 return isInRecents() ? false : mActivity.getCurrentDirectory().isCreateSupported();
316 }
317
Ben Linebf2a172016-06-03 13:46:52 -0700318 public boolean isInRecents() {
319 return mActivity.getCurrentDirectory() == null;
320 }
321
322 public boolean canCreateDirectory() {
323 return mActivity.canCreateDirectory();
324 }
325 }
326}