| /* | |
| * Copyright (C) 2016 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| package com.android.documentsui.files; | |
| import android.content.Context; | |
| import android.content.res.Resources; | |
| import android.net.Uri; | |
| import android.view.KeyEvent; | |
| import android.view.KeyboardShortcutGroup; | |
| import android.view.KeyboardShortcutInfo; | |
| import android.view.Menu; | |
| import android.view.MenuInflater; | |
| import android.view.MenuItem; | |
| import android.view.View; | |
| import androidx.fragment.app.Fragment; | |
| import androidx.recyclerview.selection.SelectionTracker; | |
| import com.android.documentsui.R; | |
| import com.android.documentsui.base.DocumentInfo; | |
| import com.android.documentsui.base.Features; | |
| import com.android.documentsui.base.Lookup; | |
| import com.android.documentsui.base.LookupApplicationName; | |
| import com.android.documentsui.base.Menus; | |
| import com.android.documentsui.base.RootInfo; | |
| import com.android.documentsui.base.Shared; | |
| import com.android.documentsui.base.State; | |
| import com.android.documentsui.base.UserId; | |
| import com.android.documentsui.queries.SearchViewManager; | |
| import java.util.List; | |
| import java.util.function.IntFunction; | |
| import java.util.function.IntSupplier; | |
| public final class MenuManager extends com.android.documentsui.MenuManager { | |
| private final Features mFeatures; | |
| private final Context mContext; | |
| private final SelectionTracker<String> mSelectionManager; | |
| private final Lookup<String, Uri> mUriLookup; | |
| private final LookupApplicationName mAppNameLookup; | |
| public MenuManager( | |
| Features features, | |
| SearchViewManager searchManager, | |
| State displayState, | |
| DirectoryDetails dirDetails, | |
| Context context, | |
| SelectionTracker<String> selectionManager, | |
| LookupApplicationName appNameLookup, | |
| Lookup<String, Uri> uriLookup, | |
| IntSupplier filesCountSupplier) { | |
| super(searchManager, displayState, dirDetails, filesCountSupplier); | |
| mFeatures = features; | |
| mContext = context; | |
| mSelectionManager = selectionManager; | |
| mAppNameLookup = appNameLookup; | |
| mUriLookup = uriLookup; | |
| } | |
| @Override | |
| public void updateKeyboardShortcutsMenu( | |
| List<KeyboardShortcutGroup> data, IntFunction<String> stringSupplier) { | |
| KeyboardShortcutGroup group = new KeyboardShortcutGroup( | |
| stringSupplier.apply(R.string.app_label)); | |
| group.addItem(new KeyboardShortcutInfo( | |
| stringSupplier.apply(R.string.menu_cut_to_clipboard), KeyEvent.KEYCODE_X, | |
| KeyEvent.META_CTRL_ON)); | |
| group.addItem(new KeyboardShortcutInfo( | |
| stringSupplier.apply(R.string.menu_copy_to_clipboard), KeyEvent.KEYCODE_C, | |
| KeyEvent.META_CTRL_ON)); | |
| group.addItem(new KeyboardShortcutInfo( | |
| stringSupplier.apply(R.string.menu_paste_from_clipboard), KeyEvent.KEYCODE_V, | |
| KeyEvent.META_CTRL_ON)); | |
| group.addItem(new KeyboardShortcutInfo( | |
| stringSupplier.apply(R.string.menu_create_dir), KeyEvent.KEYCODE_E, | |
| KeyEvent.META_CTRL_ON)); | |
| group.addItem(new KeyboardShortcutInfo( | |
| stringSupplier.apply(R.string.menu_select_all), KeyEvent.KEYCODE_A, | |
| KeyEvent.META_CTRL_ON)); | |
| group.addItem(new KeyboardShortcutInfo( | |
| stringSupplier.apply(R.string.menu_new_window), KeyEvent.KEYCODE_N, | |
| KeyEvent.META_CTRL_ON)); | |
| data.add(group); | |
| } | |
| @Override | |
| public void showContextMenu(Fragment f, View v, float x, float y) { | |
| // Register context menu here so long-press doesn't trigger this context floating menu. | |
| f.registerForContextMenu(v); | |
| v.showContextMenu(x, y); | |
| f.unregisterForContextMenu(v); | |
| } | |
| @Override | |
| public void inflateContextMenuForContainer( | |
| Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) { | |
| inflater.inflate(R.menu.container_context_menu, menu); | |
| updateContextMenuForContainer(menu, selectionDetails); | |
| } | |
| @Override | |
| public void inflateContextMenuForDocs( | |
| Menu menu, MenuInflater inflater, SelectionDetails selectionDetails) { | |
| final boolean hasDir = selectionDetails.containsDirectories(); | |
| final boolean hasFile = selectionDetails.containsFiles(); | |
| assert(hasDir || hasFile); | |
| if (!hasDir) { | |
| inflater.inflate(R.menu.file_context_menu, menu); | |
| updateContextMenuForFiles(menu, selectionDetails); | |
| return; | |
| } | |
| if (!hasFile) { | |
| inflater.inflate(R.menu.dir_context_menu, menu); | |
| updateContextMenuForDirs(menu, selectionDetails); | |
| return; | |
| } | |
| inflater.inflate(R.menu.mixed_context_menu, menu); | |
| updateContextMenu(menu, selectionDetails); | |
| } | |
| @Override | |
| protected void updateSettings(MenuItem settings, RootInfo root) { | |
| Menus.setEnabledAndVisible(settings, root.hasSettings()); | |
| } | |
| @Override | |
| protected void updateEject(MenuItem eject, RootInfo root) { | |
| Menus.setEnabledAndVisible(eject, root.supportsEject() && !root.ejecting); | |
| } | |
| @Override | |
| protected void updateSettings(MenuItem settings) { | |
| boolean enabled = mDirDetails.hasRootSettings(); | |
| Menus.setEnabledAndVisible(settings, enabled); | |
| } | |
| @Override | |
| protected void updateNewWindow(MenuItem newWindow) { | |
| Menus.setEnabledAndVisible(newWindow, true); | |
| } | |
| @Override | |
| protected void updateOpenWith(MenuItem openWith, SelectionDetails selectionDetails) { | |
| Menus.setEnabledAndVisible(openWith, selectionDetails.canOpenWith()); | |
| } | |
| @Override | |
| protected void updateOpenInNewWindow( | |
| MenuItem openInNewWindow, SelectionDetails selectionDetails) { | |
| Menus.setEnabledAndVisible(openInNewWindow, selectionDetails.size() == 1 | |
| && !selectionDetails.containsPartialFiles()); | |
| } | |
| @Override | |
| protected void updateOpenInNewWindow(MenuItem openInNewWindow, RootInfo root) { | |
| assert(openInNewWindow.isVisible() && openInNewWindow.isEnabled()); | |
| } | |
| @Override | |
| protected void updateMoveTo(MenuItem moveTo, SelectionDetails selectionDetails) { | |
| Menus.setEnabledAndVisible(moveTo, | |
| !selectionDetails.containsPartialFiles() && selectionDetails.canDelete()); | |
| } | |
| @Override | |
| protected void updateCopyTo(MenuItem copyTo, SelectionDetails selectionDetails) { | |
| Menus.setEnabledAndVisible(copyTo, !selectionDetails.containsPartialFiles() | |
| && !selectionDetails.canExtract()); | |
| } | |
| @Override | |
| protected void updateCompress(MenuItem compress, SelectionDetails selectionDetails) { | |
| final boolean readOnly = !mDirDetails.canCreateDoc(); | |
| Menus.setEnabledAndVisible(compress, mFeatures.isArchiveCreationEnabled() | |
| && !readOnly | |
| && !selectionDetails.containsPartialFiles() | |
| && !selectionDetails.canExtract()); | |
| } | |
| @Override | |
| protected void updateExtractTo(MenuItem extractTo, SelectionDetails selectionDetails) { | |
| boolean enabled = selectionDetails.canExtract(); | |
| Menus.setEnabledAndVisible(extractTo, enabled); | |
| } | |
| @Override | |
| protected void updatePasteInto(MenuItem pasteInto, SelectionDetails selectionDetails) { | |
| Menus.setEnabledAndVisible(pasteInto, | |
| selectionDetails.canPasteInto() && mDirDetails.hasItemsToPaste()); | |
| } | |
| @Override | |
| protected void updatePasteInto(MenuItem pasteInto, RootInfo root, DocumentInfo docInfo) { | |
| Menus.setEnabledAndVisible(pasteInto, root.supportsCreate() | |
| && docInfo != null | |
| && docInfo.isCreateSupported() | |
| && mDirDetails.hasItemsToPaste()); | |
| } | |
| @Override | |
| protected void updateSelectAll(MenuItem selectAll) { | |
| Menus.setEnabledAndVisible(selectAll, true); | |
| } | |
| @Override | |
| protected void updateSelectAll(MenuItem selectAll, SelectionDetails selectionDetails) { | |
| final boolean visible = selectionDetails.size() < mFilesCountSupplier.getAsInt(); | |
| Menus.setEnabledAndVisible(selectAll, visible); | |
| } | |
| @Override | |
| protected void updateDeselectAll(MenuItem deselectAll, SelectionDetails selectionDetails) { | |
| final boolean visible = selectionDetails.size() == mFilesCountSupplier.getAsInt(); | |
| Menus.setEnabledAndVisible(deselectAll, visible); | |
| } | |
| @Override | |
| protected void updateCreateDir(MenuItem createDir) { | |
| Menus.setEnabledAndVisible(createDir, mDirDetails.canCreateDirectory()); | |
| } | |
| @Override | |
| protected void updateShare(MenuItem share, SelectionDetails selectionDetails) { | |
| boolean enabled = !selectionDetails.containsDirectories() | |
| && !selectionDetails.containsPartialFiles() | |
| && !selectionDetails.canExtract(); | |
| Menus.setEnabledAndVisible(share, enabled); | |
| } | |
| @Override | |
| protected void updateDelete(MenuItem delete, SelectionDetails selectionDetails) { | |
| boolean enabled = selectionDetails.canDelete(); | |
| Menus.setEnabledAndVisible(delete, enabled); | |
| } | |
| @Override | |
| protected void updateRename(MenuItem rename, SelectionDetails selectionDetails) { | |
| Menus.setEnabledAndVisible(rename, | |
| !selectionDetails.containsPartialFiles() && selectionDetails.canRename()); | |
| } | |
| @Override | |
| protected void updateInspect(MenuItem inspect) { | |
| boolean visible = mFeatures.isInspectorEnabled(); | |
| Menus.setEnabledAndVisible(inspect, visible && mDirDetails.canInspectDirectory()); | |
| } | |
| @Override | |
| protected void updateInspect(MenuItem inspect, SelectionDetails selectionDetails) { | |
| boolean visible = mFeatures.isInspectorEnabled() && selectionDetails.size() <= 1; | |
| Menus.setEnabledAndVisible(inspect, visible); | |
| } | |
| @Override | |
| protected void updateViewInOwner(MenuItem view, SelectionDetails selectionDetails) { | |
| if (selectionDetails.canViewInOwner() && | |
| mSelectionManager.getSelection().iterator().hasNext()) { | |
| Menus.setEnabledAndVisible(view, true); | |
| Resources res = mContext.getResources(); | |
| String selectedModelId = mSelectionManager.getSelection().iterator().next(); | |
| Uri selectedUri = mUriLookup.lookup(selectedModelId); | |
| String appName = mAppNameLookup.getApplicationName(UserId.DEFAULT_USER, | |
| selectedUri.getAuthority()); | |
| String title = res.getString(R.string.menu_view_in_owner, appName); | |
| view.setTitle(title); | |
| } | |
| else { | |
| Menus.setEnabledAndVisible(view, false); | |
| } | |
| } | |
| @Override | |
| protected void updateLauncher(MenuItem launcher) { | |
| Menus.setEnabledAndVisible(launcher, mState.debugMode); | |
| launcher.setTitle(Shared.isLauncherEnabled(mContext) | |
| ? "Hide launcher icon" : "Show launcher icon"); | |
| } | |
| } |