1 /* 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 17 package com.android.documentsui.files; 18 19 import android.app.Fragment; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.net.Uri; 23 import android.view.KeyEvent; 24 import android.view.KeyboardShortcutGroup; 25 import android.view.KeyboardShortcutInfo; 26 import android.view.Menu; 27 import android.view.MenuInflater; 28 import android.view.MenuItem; 29 import android.view.View; 30 31 import com.android.documentsui.R; 32 import com.android.documentsui.base.DocumentInfo; 33 import com.android.documentsui.base.Features; 34 import com.android.documentsui.base.Lookup; 35 import com.android.documentsui.base.RootInfo; 36 import com.android.documentsui.base.State; 37 import com.android.documentsui.queries.SearchViewManager; 38 import com.android.documentsui.selection.SelectionManager; 39 40 import java.util.List; 41 import java.util.function.Function; 42 import java.util.function.IntFunction; 43 44 public final class MenuManager extends com.android.documentsui.MenuManager { 45 46 private final Features mFeatures; 47 private final Context mContext; 48 private final SelectionManager mSelectionManager; 49 private final Lookup<String, Uri> mUriLookup; 50 private final Lookup<String, String> mAppNameLookup; 51 MenuManager( Features features, SearchViewManager searchManager, State displayState, DirectoryDetails dirDetails, Context context, SelectionManager selectionManager, Lookup<String, String> appNameLookup, Lookup<String, Uri> uriLookup)52 public MenuManager( 53 Features features, 54 SearchViewManager searchManager, 55 State displayState, 56 DirectoryDetails dirDetails, 57 Context context, 58 SelectionManager selectionManager, 59 Lookup<String, String> appNameLookup, 60 Lookup<String, Uri> uriLookup) { 61 super(searchManager, displayState, dirDetails); 62 mFeatures = features; 63 mContext = context; 64 mSelectionManager = selectionManager; 65 mAppNameLookup = appNameLookup; 66 mUriLookup = uriLookup; 67 } 68 69 @Override updateOptionMenu(Menu menu)70 public void updateOptionMenu(Menu menu) { 71 super.updateOptionMenu(menu); 72 73 // It hides icon if searching in progress 74 mSearchManager.updateMenu(); 75 } 76 77 @Override updateKeyboardShortcutsMenu( List<KeyboardShortcutGroup> data, IntFunction<String> stringSupplier)78 public void updateKeyboardShortcutsMenu( 79 List<KeyboardShortcutGroup> data, IntFunction<String> stringSupplier) { 80 KeyboardShortcutGroup group = new KeyboardShortcutGroup( 81 stringSupplier.apply(R.string.app_label)); 82 group.addItem(new KeyboardShortcutInfo( 83 stringSupplier.apply(R.string.menu_cut_to_clipboard), KeyEvent.KEYCODE_X, 84 KeyEvent.META_CTRL_ON)); 85 group.addItem(new KeyboardShortcutInfo( 86 stringSupplier.apply(R.string.menu_copy_to_clipboard), KeyEvent.KEYCODE_C, 87 KeyEvent.META_CTRL_ON)); 88 group.addItem(new KeyboardShortcutInfo( 89 stringSupplier.apply(R.string.menu_paste_from_clipboard), KeyEvent.KEYCODE_V, 90 KeyEvent.META_CTRL_ON)); 91 group.addItem(new KeyboardShortcutInfo( 92 stringSupplier.apply(R.string.menu_create_dir), KeyEvent.KEYCODE_E, 93 KeyEvent.META_CTRL_ON)); 94 group.addItem(new KeyboardShortcutInfo( 95 stringSupplier.apply(R.string.menu_select_all), KeyEvent.KEYCODE_A, 96 KeyEvent.META_CTRL_ON)); 97 group.addItem(new KeyboardShortcutInfo( 98 stringSupplier.apply(R.string.menu_new_window), KeyEvent.KEYCODE_N, 99 KeyEvent.META_CTRL_ON)); 100 data.add(group); 101 } 102 103 @Override showContextMenu(Fragment f, View v, float x, float y)104 public void showContextMenu(Fragment f, View v, float x, float y) { 105 // Register context menu here so long-press doesn't trigger this context floating menu. 106 f.registerForContextMenu(v); 107 v.showContextMenu(x, y); 108 f.unregisterForContextMenu(v); 109 } 110 111 @Override inflateContextMenuForContainer(Menu menu, MenuInflater inflater)112 public void inflateContextMenuForContainer(Menu menu, MenuInflater inflater) { 113 inflater.inflate(R.menu.container_context_menu, menu); 114 updateContextMenuForContainer(menu); 115 } 116 117 @Override inflateContextMenuForDocs( Menu menu, MenuInflater inflater, SelectionDetails selectionDetails)118 public void inflateContextMenuForDocs( 119 Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) { 120 final boolean hasDir = selectionDetails.containsDirectories(); 121 final boolean hasFile = selectionDetails.containsFiles(); 122 123 assert(hasDir || hasFile); 124 if (!hasDir) { 125 inflater.inflate(R.menu.file_context_menu, menu); 126 updateContextMenuForFiles(menu, selectionDetails); 127 return; 128 } 129 130 if (!hasFile) { 131 inflater.inflate(R.menu.dir_context_menu, menu); 132 updateContextMenuForDirs(menu, selectionDetails); 133 return; 134 } 135 136 inflater.inflate(R.menu.mixed_context_menu, menu); 137 updateContextMenu(menu, selectionDetails); 138 } 139 140 @Override updateSettings(MenuItem settings, RootInfo root)141 protected void updateSettings(MenuItem settings, RootInfo root) { 142 settings.setVisible(true); 143 settings.setEnabled(root.hasSettings()); 144 } 145 146 @Override updateEject(MenuItem eject, RootInfo root)147 protected void updateEject(MenuItem eject, RootInfo root) { 148 eject.setVisible(root.supportsEject()); 149 eject.setEnabled(!root.ejecting); 150 } 151 152 @Override updateSettings(MenuItem settings)153 protected void updateSettings(MenuItem settings) { 154 boolean enabled = mDirDetails.hasRootSettings(); 155 settings.setVisible(enabled); 156 settings.setEnabled(enabled); 157 } 158 159 @Override updateNewWindow(MenuItem newWindow)160 protected void updateNewWindow(MenuItem newWindow) { 161 newWindow.setVisible(true); 162 } 163 164 @Override updateOpenInContextMenu(MenuItem open, SelectionDetails selectionDetails)165 protected void updateOpenInContextMenu(MenuItem open, SelectionDetails selectionDetails) { 166 open.setVisible(true); 167 open.setEnabled(selectionDetails.size() == 1 168 && !selectionDetails.containsPartialFiles()); 169 } 170 171 @Override updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails)172 protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) { 173 openWith.setVisible(true); 174 openWith.setEnabled(selectionDetails.canOpenWith()); 175 } 176 177 @Override updateOpenInNewWindow( MenuItem openInNewWindow, SelectionDetails selectionDetails)178 protected void updateOpenInNewWindow( 179 MenuItem openInNewWindow, SelectionDetails selectionDetails) { 180 openInNewWindow.setVisible(true); 181 openInNewWindow.setEnabled(selectionDetails.size() == 1 182 && !selectionDetails.containsPartialFiles()); 183 } 184 185 @Override updateOpenInNewWindow(MenuItem openInNewWindow, RootInfo root)186 protected void updateOpenInNewWindow(MenuItem openInNewWindow, RootInfo root) { 187 assert(openInNewWindow.isVisible() && openInNewWindow.isEnabled()); 188 } 189 190 @Override updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails)191 protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) { 192 moveTo.setVisible(true); 193 moveTo.setEnabled(!selectionDetails.containsPartialFiles() && selectionDetails.canDelete()); 194 } 195 196 @Override updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails)197 protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) { 198 copyTo.setVisible(true); 199 copyTo.setEnabled(!selectionDetails.containsPartialFiles() && 200 !selectionDetails.canExtract()); 201 } 202 203 @Override updateCompress(MenuItem compress, SelectionDetails selectionDetails)204 protected void updateCompress(MenuItem compress, SelectionDetails selectionDetails) { 205 final boolean readOnly = !mDirDetails.canCreateDoc(); 206 compress.setVisible(mFeatures.isArchiveCreationEnabled()); 207 compress.setEnabled(!readOnly && !selectionDetails.containsPartialFiles() && 208 !selectionDetails.canExtract()); 209 } 210 211 @Override updateExtractTo(MenuItem extractTo, SelectionDetails selectionDetails)212 protected void updateExtractTo(MenuItem extractTo, SelectionDetails selectionDetails) { 213 boolean enabled = selectionDetails.canExtract(); 214 extractTo.setVisible(enabled); 215 extractTo.setEnabled(enabled); 216 } 217 218 @Override updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails)219 protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) { 220 pasteInto.setVisible(true); 221 pasteInto.setEnabled(selectionDetails.canPasteInto() && mDirDetails.hasItemsToPaste()); 222 } 223 224 @Override updatePasteInto(MenuItem pasteInto, RootInfo root, DocumentInfo docInfo)225 protected void updatePasteInto(MenuItem pasteInto, RootInfo root, DocumentInfo docInfo) { 226 pasteInto.setVisible(true); 227 pasteInto.setEnabled(root.supportsCreate() 228 && docInfo != null 229 && docInfo.isCreateSupported() 230 && mDirDetails.hasItemsToPaste()); 231 } 232 233 @Override updateSelectAll(MenuItem selectAll)234 protected void updateSelectAll(MenuItem selectAll) { 235 selectAll.setVisible(true); 236 selectAll.setEnabled(true); 237 } 238 239 @Override updateCreateDir(MenuItem createDir)240 protected void updateCreateDir(MenuItem createDir) { 241 createDir.setVisible(true); 242 createDir.setEnabled(mDirDetails.canCreateDirectory()); 243 } 244 245 @Override updateShare(MenuItem share, SelectionDetails selectionDetails)246 protected void updateShare(MenuItem share, SelectionDetails selectionDetails) { 247 boolean enabled = !selectionDetails.containsDirectories() 248 && !selectionDetails.containsPartialFiles() 249 && !selectionDetails.canExtract(); 250 share.setVisible(enabled); 251 share.setEnabled(enabled); 252 } 253 254 @Override updateDelete(MenuItem delete, SelectionDetails selectionDetails)255 protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) { 256 boolean enabled = selectionDetails.canDelete(); 257 delete.setVisible(enabled); 258 delete.setEnabled(enabled); 259 } 260 261 @Override updateRename(MenuItem rename, SelectionDetails selectionDetails)262 protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) { 263 rename.setVisible(true); 264 rename.setEnabled(!selectionDetails.containsPartialFiles() && selectionDetails.canRename()); 265 } 266 267 @Override updateViewInOwner(MenuItem view, SelectionDetails selectionDetails)268 protected void updateViewInOwner(MenuItem view, SelectionDetails selectionDetails) { 269 if (selectionDetails.canViewInOwner()) { 270 view.setVisible(true); 271 view.setEnabled(true); 272 Resources res = mContext.getResources(); 273 String selectedModelId = mSelectionManager.getSelection().iterator().next(); 274 Uri selectedUri = mUriLookup.lookup(selectedModelId); 275 String appName = mAppNameLookup.lookup(selectedUri.getAuthority()); 276 String title = res.getString(R.string.menu_view_in_owner, appName); 277 view.setTitle(title); 278 } 279 else { 280 view.setVisible(false); 281 } 282 } 283 } 284