blob: f7685e186a896feaa5d12d4788718ebc25795801 [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;
Garfield Tan06c4b112016-09-14 11:05:58 -070030import com.android.documentsui.dirlist.DirectoryFragment;
Garfield Tanb285b402016-09-21 17:12:18 -070031import com.android.documentsui.sidebar.RootsFragment;
Garfield Tan239ab972016-09-16 13:33:48 -070032import com.android.internal.annotations.VisibleForTesting;
Ben Lin5668b862016-06-28 17:12:52 -070033
Ben Linebf2a172016-06-03 13:46:52 -070034public abstract class MenuManager {
Ben Lin7c35b032016-05-31 13:24:01 -070035
Garfield Tan25676032016-09-19 13:52:35 -070036 final protected SearchViewManager mSearchManager;
Steve McKaye5d6ca22016-09-19 20:27:24 -070037 final protected State mState;
38 final protected DirectoryDetails mDirDetails;
Ben Lin25679912016-06-17 11:48:57 -070039
Steve McKaye5d6ca22016-09-19 20:27:24 -070040 public MenuManager(
41 SearchViewManager searchManager,
42 State displayState,
43 DirectoryDetails dirDetails) {
Ben Lin25679912016-06-17 11:48:57 -070044 mSearchManager = searchManager;
45 mState = displayState;
Steve McKaye5d6ca22016-09-19 20:27:24 -070046 mDirDetails = dirDetails;
Ben Lin25679912016-06-17 11:48:57 -070047 }
48
Garfield Tan06c4b112016-09-14 11:05:58 -070049 /** @see ActionModeController */
Ben Linebf2a172016-06-03 13:46:52 -070050 public void updateActionMenu(Menu menu, SelectionDetails selection) {
Garfield Tan06c4b112016-09-14 11:05:58 -070051 updateOpenInActionMode(menu.findItem(R.id.menu_open), selection);
Ben Linebf2a172016-06-03 13:46:52 -070052 updateDelete(menu.findItem(R.id.menu_delete), selection);
53 updateShare(menu.findItem(R.id.menu_share), selection);
54 updateRename(menu.findItem(R.id.menu_rename), selection);
Garfield Tan06c4b112016-09-14 11:05:58 -070055 updateSelectAll(menu.findItem(R.id.menu_select_all));
Ben Linebf2a172016-06-03 13:46:52 -070056 updateMoveTo(menu.findItem(R.id.menu_move_to), selection);
57 updateCopyTo(menu.findItem(R.id.menu_copy_to), selection);
Ben Lin7c35b032016-05-31 13:24:01 -070058
Ben Linebf2a172016-06-03 13:46:52 -070059 Menus.disableHiddenItems(menu);
60 }
Ben Lin7c35b032016-05-31 13:24:01 -070061
Garfield Tan06c4b112016-09-14 11:05:58 -070062 /** @see BaseActivity#onPrepareOptionsMenu */
Steve McKaye5d6ca22016-09-19 20:27:24 -070063 public void updateOptionMenu(Menu menu) {
64 updateCreateDir(menu.findItem(R.id.menu_create_dir));
65 updateSettings(menu.findItem(R.id.menu_settings));
66 updateNewWindow(menu.findItem(R.id.menu_new_window));
67 updateModePicker(menu.findItem(R.id.menu_grid), menu.findItem(R.id.menu_list));
Garfield, Tan11d23482016-08-05 09:33:29 -070068 // Sort menu item is managed by SortMenuManager
Steve McKaye5d6ca22016-09-19 20:27:24 -070069 updateAdvanced(menu.findItem(R.id.menu_advanced));
Ben Lin7c35b032016-05-31 13:24:01 -070070
Ben Linebf2a172016-06-03 13:46:52 -070071 Menus.disableHiddenItems(menu);
72 }
Ben Lin7c35b032016-05-31 13:24:01 -070073
Garfield Tan06c4b112016-09-14 11:05:58 -070074 /**
Garfield Tan239ab972016-09-16 13:33:48 -070075 * Called when we needs {@link MenuManager} to ask Android to show context menu for us.
76 * {@link MenuManager} can choose to defeat this request.
77 *
78 * {@link #inflateContextMenuForDocs} and {@link #inflateContextMenuForContainer} are called
79 * afterwards when Android asks us to provide the content of context menus, so they're not
80 * correct locations to suppress context menus.
81 */
82 public void showContextMenu(Fragment f, View v, float x, float y) {
83 // Pickers don't have any context menu at this moment.
84 }
85
Steve McKaye5d6ca22016-09-19 20:27:24 -070086 public void inflateContextMenuForContainer(Menu menu, MenuInflater inflater) {
Garfield Tan239ab972016-09-16 13:33:48 -070087 throw new UnsupportedOperationException("Pickers don't allow context menu.");
88 }
89
90 public void inflateContextMenuForDocs(
91 Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) {
92 throw new UnsupportedOperationException("Pickers don't allow context menu.");
93 }
94
95 /**
Garfield Tan06c4b112016-09-14 11:05:58 -070096 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -070097 *
Garfield Tan06c4b112016-09-14 11:05:58 -070098 * Called when user tries to generate a context menu anchored to a file when the selection
99 * doesn't contain any folder.
100 *
101 * @param selectionDetails
102 * containsFiles may return false because this may be called when user right clicks on an
103 * unselectable item in pickers
104 */
Garfield Tan239ab972016-09-16 13:33:48 -0700105 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700106 public void updateContextMenuForFiles(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700107 assert(selectionDetails != null);
108
109 MenuItem share = menu.findItem(R.id.menu_share);
110 MenuItem open = menu.findItem(R.id.menu_open);
111 MenuItem openWith = menu.findItem(R.id.menu_open_with);
112 MenuItem rename = menu.findItem(R.id.menu_rename);
113
114 updateShare(share, selectionDetails);
115 updateOpenInContextMenu(open, selectionDetails);
116 updateOpenWith(openWith, selectionDetails);
117 updateRename(rename, selectionDetails);
118
119 updateContextMenu(menu, selectionDetails);
120 }
121
122 /**
123 * @see DirectoryFragment#onCreateContextMenu
124 *
125 * Called when user tries to generate a context menu anchored to a folder when the selection
126 * doesn't contain any file.
127 *
128 * @param selectionDetails
129 * containDirectories may return false because this may be called when user right clicks on
130 * an unselectable item in pickers
131 */
Garfield Tan239ab972016-09-16 13:33:48 -0700132 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700133 public void updateContextMenuForDirs(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700134 assert(selectionDetails != null);
135
136 MenuItem openInNewWindow = menu.findItem(R.id.menu_open_in_new_window);
137 MenuItem rename = menu.findItem(R.id.menu_rename);
138 MenuItem pasteInto = menu.findItem(R.id.menu_paste_into_folder);
139
140 updateOpenInNewWindow(openInNewWindow, selectionDetails);
141 updateRename(rename, selectionDetails);
142 updatePasteInto(pasteInto, selectionDetails);
143
144 updateContextMenu(menu, selectionDetails);
145 }
146
147 /**
148 * @see DirectoryFragment#onCreateContextMenu
149 *
150 * Update shared context menu items of both files and folders context menus.
151 */
Garfield Tan239ab972016-09-16 13:33:48 -0700152 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700153 public void updateContextMenu(Menu menu, SelectionDetails selectionDetails) {
Ben Linb2dfa122016-08-11 17:42:57 -0700154 assert(selectionDetails != null);
155
156 MenuItem cut = menu.findItem(R.id.menu_cut_to_clipboard);
157 MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
Ben Linb2dfa122016-08-11 17:42:57 -0700158 MenuItem delete = menu.findItem(R.id.menu_delete);
Ben Linb2dfa122016-08-11 17:42:57 -0700159
Garfield Tan06c4b112016-09-14 11:05:58 -0700160 final boolean canCopy =
161 selectionDetails.size() > 0 && !selectionDetails.containsPartialFiles();
162 final boolean canDelete = selectionDetails.canDelete();
163 cut.setEnabled(canCopy && canDelete);
164 copy.setEnabled(canCopy);
165 delete.setEnabled(canDelete);
Ben Linb2dfa122016-08-11 17:42:57 -0700166 }
167
Garfield Tan06c4b112016-09-14 11:05:58 -0700168 /**
169 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -0700170 *
171 * Called when user tries to generate a context menu anchored to an empty pane.
Garfield Tan06c4b112016-09-14 11:05:58 -0700172 */
Garfield Tan239ab972016-09-16 13:33:48 -0700173 @VisibleForTesting
Steve McKaye5d6ca22016-09-19 20:27:24 -0700174 public void updateContextMenuForContainer(Menu menu) {
Ben Linebf2a172016-06-03 13:46:52 -0700175 MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
Garfield Tan06c4b112016-09-14 11:05:58 -0700176 MenuItem selectAll = menu.findItem(R.id.menu_select_all);
Garfield Tand3307272016-10-10 13:33:25 -0700177 MenuItem createDir = menu.findItem(R.id.menu_create_dir);
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);
Garfield Tand3307272016-10-10 13:33:25 -0700181 updateCreateDir(createDir);
Ben Linebf2a172016-06-03 13:46:52 -0700182 }
Ben Lin7c35b032016-05-31 13:24:01 -0700183
Garfield Tan06c4b112016-09-14 11:05:58 -0700184 /**
185 * @see RootsFragment#onCreateContextMenu
186 */
Ben Lin8e912582016-09-23 14:25:14 -0700187 public void updateRootContextMenu(Menu menu, RootInfo root, DocumentInfo docInfo) {
Ben Lin5668b862016-06-28 17:12:52 -0700188 MenuItem eject = menu.findItem(R.id.menu_eject_root);
Garfield Tanb285b402016-09-21 17:12:18 -0700189 MenuItem pasteInto = menu.findItem(R.id.menu_paste_into_folder);
190 MenuItem openInNewWindow = menu.findItem(R.id.menu_open_in_new_window);
191 MenuItem settings = menu.findItem(R.id.menu_settings);
Ben Lin5668b862016-06-28 17:12:52 -0700192
Ben Lin5668b862016-06-28 17:12:52 -0700193 updateEject(eject, root);
Ben Lin8e912582016-09-23 14:25:14 -0700194 updatePasteInto(pasteInto, root, docInfo);
Garfield Tanb285b402016-09-21 17:12:18 -0700195 updateOpenInNewWindow(openInNewWindow, root);
196 updateSettings(settings, root);
Ben Lin5668b862016-06-28 17:12:52 -0700197 }
198
Steve McKaye5d6ca22016-09-19 20:27:24 -0700199 protected void updateModePicker(MenuItem grid, MenuItem list) {
Ben Lin25679912016-06-17 11:48:57 -0700200 grid.setVisible(mState.derivedMode != State.MODE_GRID);
201 list.setVisible(mState.derivedMode != State.MODE_LIST);
202 }
203
Steve McKaye5d6ca22016-09-19 20:27:24 -0700204 protected void updateAdvanced(MenuItem advanced) {
Ben Lin25679912016-06-17 11:48:57 -0700205 advanced.setVisible(mState.showAdvancedOption);
206 advanced.setTitle(mState.showAdvancedOption && mState.showAdvanced
207 ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
208 }
209
Steve McKaye5d6ca22016-09-19 20:27:24 -0700210 protected void updateSettings(MenuItem settings) {
Ben Lin25679912016-06-17 11:48:57 -0700211 settings.setVisible(false);
212 }
213
Garfield Tan25676032016-09-19 13:52:35 -0700214 protected void updateSettings(MenuItem settings, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700215 settings.setVisible(false);
216 }
217
Garfield Tan25676032016-09-19 13:52:35 -0700218 protected void updateEject(MenuItem eject, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700219 eject.setVisible(false);
220 }
221
Steve McKaye5d6ca22016-09-19 20:27:24 -0700222 protected void updateNewWindow(MenuItem newWindow) {
Ben Lin25679912016-06-17 11:48:57 -0700223 newWindow.setVisible(false);
224 }
225
Garfield Tan25676032016-09-19 13:52:35 -0700226 protected void updateOpenInActionMode(MenuItem open, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700227 open.setVisible(false);
228 }
229
Garfield Tan25676032016-09-19 13:52:35 -0700230 protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700231 openWith.setVisible(false);
232 }
233
Garfield Tan25676032016-09-19 13:52:35 -0700234 protected void updateOpenInNewWindow(
235 MenuItem openInNewWindow, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700236 openInNewWindow.setVisible(false);
237 }
238
Garfield Tanb285b402016-09-21 17:12:18 -0700239 protected void updateOpenInNewWindow(
240 MenuItem openInNewWindow, RootInfo root) {
241 openInNewWindow.setVisible(false);
242 }
243
Garfield Tan25676032016-09-19 13:52:35 -0700244 protected void updateShare(MenuItem share, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700245 share.setVisible(false);
246 }
247
Garfield Tan25676032016-09-19 13:52:35 -0700248 protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700249 delete.setVisible(false);
250 }
251
Garfield Tan25676032016-09-19 13:52:35 -0700252 protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700253 rename.setVisible(false);
254 }
255
Garfield Tan25676032016-09-19 13:52:35 -0700256 protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700257 moveTo.setVisible(false);
258 }
259
Garfield Tan25676032016-09-19 13:52:35 -0700260 protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700261 copyTo.setVisible(false);
262 }
263
Garfield Tan25676032016-09-19 13:52:35 -0700264 protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700265 pasteInto.setVisible(false);
Ben Linb2dfa122016-08-11 17:42:57 -0700266 }
267
Ben Lin8e912582016-09-23 14:25:14 -0700268 protected void updatePasteInto(MenuItem pasteInto, RootInfo root, DocumentInfo docInfo) {
Garfield Tanb285b402016-09-21 17:12:18 -0700269 pasteInto.setVisible(false);
270 }
271
Garfield Tan25676032016-09-19 13:52:35 -0700272 protected abstract void updateOpenInContextMenu(
273 MenuItem open, SelectionDetails selectionDetails);
274 protected abstract void updateSelectAll(MenuItem selectAll);
Steve McKaye5d6ca22016-09-19 20:27:24 -0700275 protected abstract void updateCreateDir(MenuItem createDir);
Ben Lin7c35b032016-05-31 13:24:01 -0700276
Ben Linebf2a172016-06-03 13:46:52 -0700277 /**
278 * Access to meta data about the selection.
279 */
280 public interface SelectionDetails {
281 boolean containsDirectories();
282
Garfield Tan06c4b112016-09-14 11:05:58 -0700283 boolean containsFiles();
284
285 int size();
286
Ben Linebf2a172016-06-03 13:46:52 -0700287 boolean containsPartialFiles();
288
289 // TODO: Update these to express characteristics instead of answering concrete questions,
290 // since the answer to those questions is (or can be) activity specific.
291 boolean canDelete();
292
293 boolean canRename();
Ben Linb2dfa122016-08-11 17:42:57 -0700294
295 boolean canPasteInto();
Ben Linebf2a172016-06-03 13:46:52 -0700296 }
297
298 public static class DirectoryDetails {
Steve McKay6525a192016-10-18 14:28:00 -0700299 private final BaseActivity<?> mActivity;
Ben Linebf2a172016-06-03 13:46:52 -0700300
Steve McKay6525a192016-10-18 14:28:00 -0700301 public DirectoryDetails(BaseActivity<?> activity) {
Ben Linebf2a172016-06-03 13:46:52 -0700302 mActivity = activity;
303 }
304
305 public boolean shouldShowFancyFeatures() {
306 return Shared.shouldShowFancyFeatures(mActivity);
307 }
308
309 public boolean hasRootSettings() {
310 return mActivity.getCurrentRoot().hasSettings();
311 }
312
313 public boolean hasItemsToPaste() {
314 return false;
315 }
316
Garfield Tan06c4b112016-09-14 11:05:58 -0700317 public boolean canCreateDoc() {
318 return isInRecents() ? false : mActivity.getCurrentDirectory().isCreateSupported();
319 }
320
Ben Linebf2a172016-06-03 13:46:52 -0700321 public boolean isInRecents() {
322 return mActivity.getCurrentDirectory() == null;
323 }
324
325 public boolean canCreateDirectory() {
326 return mActivity.canCreateDirectory();
327 }
328 }
329}