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