blob: ac45c167764135df4593e96126d63201d6399eec [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 SearchViewManager mSearchManager;
Steve McKaye5d6ca22016-09-19 20:27:24 -070035 final protected State mState;
36 final protected DirectoryDetails mDirDetails;
Ben Lin25679912016-06-17 11:48:57 -070037
Steve McKaye5d6ca22016-09-19 20:27:24 -070038 public MenuManager(
39 SearchViewManager searchManager,
40 State displayState,
41 DirectoryDetails dirDetails) {
Ben Lin25679912016-06-17 11:48:57 -070042 mSearchManager = searchManager;
43 mState = displayState;
Steve McKaye5d6ca22016-09-19 20:27:24 -070044 mDirDetails = dirDetails;
Ben Lin25679912016-06-17 11:48:57 -070045 }
46
Garfield Tan06c4b112016-09-14 11:05:58 -070047 /** @see ActionModeController */
Ben Linebf2a172016-06-03 13:46:52 -070048 public void updateActionMenu(Menu menu, SelectionDetails selection) {
Garfield Tan06c4b112016-09-14 11:05:58 -070049 updateOpenInActionMode(menu.findItem(R.id.menu_open), selection);
Ben Linebf2a172016-06-03 13:46:52 -070050 updateDelete(menu.findItem(R.id.menu_delete), selection);
51 updateShare(menu.findItem(R.id.menu_share), selection);
52 updateRename(menu.findItem(R.id.menu_rename), selection);
Garfield Tan06c4b112016-09-14 11:05:58 -070053 updateSelectAll(menu.findItem(R.id.menu_select_all));
Ben Linebf2a172016-06-03 13:46:52 -070054 updateMoveTo(menu.findItem(R.id.menu_move_to), selection);
55 updateCopyTo(menu.findItem(R.id.menu_copy_to), selection);
Ben Lin7c35b032016-05-31 13:24:01 -070056
Ben Linebf2a172016-06-03 13:46:52 -070057 Menus.disableHiddenItems(menu);
58 }
Ben Lin7c35b032016-05-31 13:24:01 -070059
Garfield Tan06c4b112016-09-14 11:05:58 -070060 /** @see BaseActivity#onPrepareOptionsMenu */
Steve McKaye5d6ca22016-09-19 20:27:24 -070061 public void updateOptionMenu(Menu menu) {
62 updateCreateDir(menu.findItem(R.id.menu_create_dir));
63 updateSettings(menu.findItem(R.id.menu_settings));
64 updateNewWindow(menu.findItem(R.id.menu_new_window));
65 updateModePicker(menu.findItem(R.id.menu_grid), menu.findItem(R.id.menu_list));
Garfield, Tan11d23482016-08-05 09:33:29 -070066 // Sort menu item is managed by SortMenuManager
Steve McKaye5d6ca22016-09-19 20:27:24 -070067 updateAdvanced(menu.findItem(R.id.menu_advanced));
Ben Lin7c35b032016-05-31 13:24:01 -070068
Ben Linebf2a172016-06-03 13:46:52 -070069 Menus.disableHiddenItems(menu);
70 }
Ben Lin7c35b032016-05-31 13:24:01 -070071
Garfield Tan06c4b112016-09-14 11:05:58 -070072 /**
Garfield Tan239ab972016-09-16 13:33:48 -070073 * Called when we needs {@link MenuManager} to ask Android to show context menu for us.
74 * {@link MenuManager} can choose to defeat this request.
75 *
76 * {@link #inflateContextMenuForDocs} and {@link #inflateContextMenuForContainer} are called
77 * afterwards when Android asks us to provide the content of context menus, so they're not
78 * correct locations to suppress context menus.
79 */
80 public void showContextMenu(Fragment f, View v, float x, float y) {
81 // Pickers don't have any context menu at this moment.
82 }
83
Steve McKaye5d6ca22016-09-19 20:27:24 -070084 public void inflateContextMenuForContainer(Menu menu, MenuInflater inflater) {
Garfield Tan239ab972016-09-16 13:33:48 -070085 throw new UnsupportedOperationException("Pickers don't allow context menu.");
86 }
87
88 public void inflateContextMenuForDocs(
89 Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) {
90 throw new UnsupportedOperationException("Pickers don't allow context menu.");
91 }
92
93 /**
Garfield Tan06c4b112016-09-14 11:05:58 -070094 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -070095 *
Garfield Tan06c4b112016-09-14 11:05:58 -070096 * Called when user tries to generate a context menu anchored to a file when the selection
97 * doesn't contain any folder.
98 *
99 * @param selectionDetails
100 * containsFiles may return false because this may be called when user right clicks on an
101 * unselectable item in pickers
102 */
Garfield Tan239ab972016-09-16 13:33:48 -0700103 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700104 public void updateContextMenuForFiles(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700105 assert(selectionDetails != null);
106
107 MenuItem share = menu.findItem(R.id.menu_share);
108 MenuItem open = menu.findItem(R.id.menu_open);
109 MenuItem openWith = menu.findItem(R.id.menu_open_with);
110 MenuItem rename = menu.findItem(R.id.menu_rename);
111
112 updateShare(share, selectionDetails);
113 updateOpenInContextMenu(open, selectionDetails);
114 updateOpenWith(openWith, selectionDetails);
115 updateRename(rename, selectionDetails);
116
117 updateContextMenu(menu, selectionDetails);
118 }
119
120 /**
121 * @see DirectoryFragment#onCreateContextMenu
122 *
123 * Called when user tries to generate a context menu anchored to a folder when the selection
124 * doesn't contain any file.
125 *
126 * @param selectionDetails
127 * containDirectories may return false because this may be called when user right clicks on
128 * an unselectable item in pickers
129 */
Garfield Tan239ab972016-09-16 13:33:48 -0700130 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700131 public void updateContextMenuForDirs(Menu menu, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700132 assert(selectionDetails != null);
133
134 MenuItem openInNewWindow = menu.findItem(R.id.menu_open_in_new_window);
135 MenuItem rename = menu.findItem(R.id.menu_rename);
136 MenuItem pasteInto = menu.findItem(R.id.menu_paste_into_folder);
137
138 updateOpenInNewWindow(openInNewWindow, selectionDetails);
139 updateRename(rename, selectionDetails);
140 updatePasteInto(pasteInto, selectionDetails);
141
142 updateContextMenu(menu, selectionDetails);
143 }
144
145 /**
146 * @see DirectoryFragment#onCreateContextMenu
147 *
148 * Update shared context menu items of both files and folders context menus.
149 */
Garfield Tan239ab972016-09-16 13:33:48 -0700150 @VisibleForTesting
Garfield Tan25676032016-09-19 13:52:35 -0700151 public void updateContextMenu(Menu menu, SelectionDetails selectionDetails) {
Ben Linb2dfa122016-08-11 17:42:57 -0700152 assert(selectionDetails != null);
153
154 MenuItem cut = menu.findItem(R.id.menu_cut_to_clipboard);
155 MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
Ben Linb2dfa122016-08-11 17:42:57 -0700156 MenuItem delete = menu.findItem(R.id.menu_delete);
Ben Linb2dfa122016-08-11 17:42:57 -0700157
Garfield Tan06c4b112016-09-14 11:05:58 -0700158 final boolean canCopy =
159 selectionDetails.size() > 0 && !selectionDetails.containsPartialFiles();
160 final boolean canDelete = selectionDetails.canDelete();
161 cut.setEnabled(canCopy && canDelete);
162 copy.setEnabled(canCopy);
163 delete.setEnabled(canDelete);
Ben Linb2dfa122016-08-11 17:42:57 -0700164 }
165
Garfield Tan06c4b112016-09-14 11:05:58 -0700166 /**
167 * @see DirectoryFragment#onCreateContextMenu
Ben Linb2dfa122016-08-11 17:42:57 -0700168 *
169 * Called when user tries to generate a context menu anchored to an empty pane.
Garfield Tan06c4b112016-09-14 11:05:58 -0700170 */
Garfield Tan239ab972016-09-16 13:33:48 -0700171 @VisibleForTesting
Steve McKaye5d6ca22016-09-19 20:27:24 -0700172 public void updateContextMenuForContainer(Menu menu) {
Ben Linebf2a172016-06-03 13:46:52 -0700173 MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
Garfield Tan06c4b112016-09-14 11:05:58 -0700174 MenuItem selectAll = menu.findItem(R.id.menu_select_all);
Ben Lin7c35b032016-05-31 13:24:01 -0700175
Steve McKaye5d6ca22016-09-19 20:27:24 -0700176 paste.setEnabled(mDirDetails.hasItemsToPaste() && mDirDetails.canCreateDoc());
Garfield Tan06c4b112016-09-14 11:05:58 -0700177 updateSelectAll(selectAll);
Ben Linebf2a172016-06-03 13:46:52 -0700178 }
Ben Lin7c35b032016-05-31 13:24:01 -0700179
Garfield Tan06c4b112016-09-14 11:05:58 -0700180 /**
181 * @see RootsFragment#onCreateContextMenu
182 */
Ben Lin5668b862016-06-28 17:12:52 -0700183 public void updateRootContextMenu(Menu menu, RootInfo root) {
184 MenuItem settings = menu.findItem(R.id.menu_settings);
185 MenuItem eject = menu.findItem(R.id.menu_eject_root);
186
187 updateSettings(settings, root);
188 updateEject(eject, root);
189 }
190
Steve McKaye5d6ca22016-09-19 20:27:24 -0700191 protected void updateModePicker(MenuItem grid, MenuItem list) {
Ben Lin25679912016-06-17 11:48:57 -0700192 grid.setVisible(mState.derivedMode != State.MODE_GRID);
193 list.setVisible(mState.derivedMode != State.MODE_LIST);
194 }
195
Steve McKaye5d6ca22016-09-19 20:27:24 -0700196 protected void updateAdvanced(MenuItem advanced) {
Ben Lin25679912016-06-17 11:48:57 -0700197 advanced.setVisible(mState.showAdvancedOption);
198 advanced.setTitle(mState.showAdvancedOption && mState.showAdvanced
199 ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
200 }
201
Steve McKaye5d6ca22016-09-19 20:27:24 -0700202 protected void updateSettings(MenuItem settings) {
Ben Lin25679912016-06-17 11:48:57 -0700203 settings.setVisible(false);
204 }
205
Garfield Tan25676032016-09-19 13:52:35 -0700206 protected void updateSettings(MenuItem settings, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700207 settings.setVisible(false);
208 }
209
Garfield Tan25676032016-09-19 13:52:35 -0700210 protected void updateEject(MenuItem eject, RootInfo root) {
Ben Lin5668b862016-06-28 17:12:52 -0700211 eject.setVisible(false);
212 }
213
Steve McKaye5d6ca22016-09-19 20:27:24 -0700214 protected void updateNewWindow(MenuItem newWindow) {
Ben Lin25679912016-06-17 11:48:57 -0700215 newWindow.setVisible(false);
216 }
217
Garfield Tan25676032016-09-19 13:52:35 -0700218 protected void updateOpenInActionMode(MenuItem open, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700219 open.setVisible(false);
220 }
221
Garfield Tan25676032016-09-19 13:52:35 -0700222 protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700223 openWith.setVisible(false);
224 }
225
Garfield Tan25676032016-09-19 13:52:35 -0700226 protected void updateOpenInNewWindow(
227 MenuItem openInNewWindow, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700228 openInNewWindow.setVisible(false);
229 }
230
Garfield Tan25676032016-09-19 13:52:35 -0700231 protected void updateShare(MenuItem share, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700232 share.setVisible(false);
233 }
234
Garfield Tan25676032016-09-19 13:52:35 -0700235 protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700236 delete.setVisible(false);
237 }
238
Garfield Tan25676032016-09-19 13:52:35 -0700239 protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700240 rename.setVisible(false);
241 }
242
Garfield Tan25676032016-09-19 13:52:35 -0700243 protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700244 moveTo.setVisible(false);
245 }
246
Garfield Tan25676032016-09-19 13:52:35 -0700247 protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) {
Ben Lin25679912016-06-17 11:48:57 -0700248 copyTo.setVisible(false);
249 }
250
Garfield Tan25676032016-09-19 13:52:35 -0700251 protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) {
Garfield Tan06c4b112016-09-14 11:05:58 -0700252 pasteInto.setVisible(false);
Ben Linb2dfa122016-08-11 17:42:57 -0700253 }
254
Garfield Tan25676032016-09-19 13:52:35 -0700255 protected abstract void updateOpenInContextMenu(
256 MenuItem open, SelectionDetails selectionDetails);
257 protected abstract void updateSelectAll(MenuItem selectAll);
Steve McKaye5d6ca22016-09-19 20:27:24 -0700258 protected abstract void updateCreateDir(MenuItem createDir);
Ben Lin7c35b032016-05-31 13:24:01 -0700259
Ben Linebf2a172016-06-03 13:46:52 -0700260 /**
261 * Access to meta data about the selection.
262 */
263 public interface SelectionDetails {
264 boolean containsDirectories();
265
Garfield Tan06c4b112016-09-14 11:05:58 -0700266 boolean containsFiles();
267
268 int size();
269
Ben Linebf2a172016-06-03 13:46:52 -0700270 boolean containsPartialFiles();
271
272 // TODO: Update these to express characteristics instead of answering concrete questions,
273 // since the answer to those questions is (or can be) activity specific.
274 boolean canDelete();
275
276 boolean canRename();
Ben Linb2dfa122016-08-11 17:42:57 -0700277
278 boolean canPasteInto();
Ben Linebf2a172016-06-03 13:46:52 -0700279 }
280
281 public static class DirectoryDetails {
282 private final BaseActivity mActivity;
283
284 public DirectoryDetails(BaseActivity activity) {
285 mActivity = activity;
286 }
287
288 public boolean shouldShowFancyFeatures() {
289 return Shared.shouldShowFancyFeatures(mActivity);
290 }
291
292 public boolean hasRootSettings() {
293 return mActivity.getCurrentRoot().hasSettings();
294 }
295
296 public boolean hasItemsToPaste() {
297 return false;
298 }
299
Garfield Tan06c4b112016-09-14 11:05:58 -0700300 public boolean canCreateDoc() {
301 return isInRecents() ? false : mActivity.getCurrentDirectory().isCreateSupported();
302 }
303
Ben Linebf2a172016-06-03 13:46:52 -0700304 public boolean isInRecents() {
305 return mActivity.getCurrentDirectory() == null;
306 }
307
308 public boolean canCreateDirectory() {
309 return mActivity.canCreateDirectory();
310 }
311 }
312}