1d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay/* 2d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * Copyright (C) 2015 The Android Open Source Project 3d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * 4d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * Licensed under the Apache License, Version 2.0 (the "License"); 5d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * you may not use this file except in compliance with the License. 6d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * You may obtain a copy of the License at 7d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * 8d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * http://www.apache.org/licenses/LICENSE-2.0 9d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * 10d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * Unless required by applicable law or agreed to in writing, software 11d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * distributed under the License is distributed on an "AS IS" BASIS, 12d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * See the License for the specific language governing permissions and 14d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay * limitations under the License. 15d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay */ 16d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 17b6006b2ef723fdbb3fef3b4a350c8d363b127d0fSteve McKaypackage com.android.documentsui.files; 18d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 19df5add4169782b33779b4f21db263216bb37e9cfSteve McKayimport static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN; 207ef09a28caedf708bfc23d4adb4cdd71094aa954Steve McKay 217295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKayimport android.app.ActivityManager.TaskDescription; 22d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKayimport android.app.FragmentManager; 23d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKayimport android.content.Intent; 24a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Songimport android.content.Context; 25a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Songimport android.graphics.drawable.AdaptiveIconDrawable; 267295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKayimport android.graphics.drawable.BitmapDrawable; 27a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Songimport android.graphics.drawable.Drawable; 28a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Songimport android.graphics.Bitmap; 29a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Songimport android.graphics.Canvas; 30a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Songimport android.graphics.Color; 31a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Songimport android.graphics.Paint; 32d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKayimport android.net.Uri; 33d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKayimport android.os.Bundle; 34aa66c43df01033ccb957bfd1d513945676866f4cBen Linimport android.support.annotation.CallSuper; 350599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKayimport android.view.KeyEvent; 36a86732316c8fe1694f4c1702cdd6c8e0faff4e18Ben Linimport android.view.KeyboardShortcutGroup; 37d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKayimport android.view.Menu; 38d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKayimport android.view.MenuItem; 39d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 40bd9f05aa36bf19d8b34d0d73a59e9bd65d3d26ebSteve McKayimport com.android.documentsui.ActionModeController; 4116e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.BaseActivity; 4216e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.DocumentsApplication; 4375b7b9039cf0efcb188e916c6f510328bfe099a8Ben Linimport com.android.documentsui.FocusManager; 4492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKayimport com.android.documentsui.Injector; 457c35b036cb0de801a093df62da92c4a94399c26cBen Linimport com.android.documentsui.MenuManager.DirectoryDetails; 4616e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKayimport com.android.documentsui.OperationDialogFragment; 47df5add4169782b33779b4f21db263216bb37e9cfSteve McKayimport com.android.documentsui.OperationDialogFragment.DialogType; 48239ab9779a40698da0fa6cff94575f5348f610a4Garfield Tanimport com.android.documentsui.ProviderExecutor; 49239ab9779a40698da0fa6cff94575f5348f610a4Garfield Tanimport com.android.documentsui.R; 50047182631669608af946480c2545a10acb2ef1bfSteve McKayimport com.android.documentsui.SharedInputHandler; 51052985f2e9687f4d62c173edeb2f0e5524082a7cSteve McKayimport com.android.documentsui.ShortcutsUpdater; 52d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.DocumentInfo; 5398f8c5f502e049a6b85439d773949cdbaa0f78aeSteve McKayimport com.android.documentsui.base.Features; 54d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.RootInfo; 55d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport com.android.documentsui.base.State; 569666ce691a4d45344460f17cec3577dbe075235aGarfield, Tanimport com.android.documentsui.clipping.DocumentClipper; 57988d8a354b00dce7e24deee187c08a4591956ac9Steve McKayimport com.android.documentsui.dirlist.AnimationView.AnimationType; 58f68210e9a1e36e65e56e0c95cfe990f0145ea63fSteve McKayimport com.android.documentsui.dirlist.DirectoryFragment; 5930b0dc1896abc67a970b61ebfd420275a31c1e18Ben Linimport com.android.documentsui.prefs.ScopedPreferences; 604f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKayimport com.android.documentsui.selection.SelectionManager; 61c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKayimport com.android.documentsui.services.FileOperationService; 62d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.sidebar.RootsFragment; 63c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKayimport com.android.documentsui.ui.DialogController; 6492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKayimport com.android.documentsui.ui.MessageBuilder; 65d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 66332d819d21dc4a719c67f6e2f8b1538bc30068b8Tomasz Mikolajewskiimport java.util.ArrayList; 67d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKayimport java.util.List; 68d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 69b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay/** 7064ac2519dc455a99cd1ac496cbf5cd76287dcce5Steve McKay * Standalone file management activity. 71b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay */ 7292ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKaypublic class FilesActivity extends BaseActivity implements ActionHandler.Addons { 73edc65bb47e1493eb12bb86c10fe706098a955658Steve McKay 746525a19f46eca7fbec21a71f833436823de03da3Steve McKay private static final String TAG = "FilesActivity"; 7592ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay static final String PREFERENCES_SCOPE = "files"; 76d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 7792ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay private Injector<ActionHandler<FilesActivity>> mInjector; 7879ae3a7d0e6dd6d2e953709a092e83002941d48fBen Lin private ActivityInputHandler mActivityInputHandler; 79047182631669608af946480c2545a10acb2ef1bfSteve McKay private SharedInputHandler mSharedInputHandler; 80b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay 81b6006b2ef723fdbb3fef3b4a350c8d363b127d0fSteve McKay public FilesActivity() { 820fbfc653868966da7fd6109b247974e0d87a2297Steve McKay super(R.layout.files_activity, TAG); 83b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay } 84d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 85e3830da96f7358c2b791d1b8573837f4110844b8Tobias Thierer // make these methods visible in this package to work around compiler bug http://b/62218600 86e3830da96f7358c2b791d1b8573837f4110844b8Tobias Thierer @Override protected boolean focusSidebar() { return super.focusSidebar(); } 87e3830da96f7358c2b791d1b8573837f4110844b8Tobias Thierer @Override protected boolean popDir() { return super.popDir(); } 88e3830da96f7358c2b791d1b8573837f4110844b8Tobias Thierer 89d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay @Override 90d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay public void onCreate(Bundle icicle) { 916525a19f46eca7fbec21a71f833436823de03da3Steve McKay 9292ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay MessageBuilder messages = new MessageBuilder(this); 935bd5cb44eacc10fe7cec7c159d6f47d127a3195bSteve McKay Features features = Features.create(this); 940ce04b7a3f2c76452f855d082cd57d5e4cab9d69Steve McKay ScopedPreferences prefs = ScopedPreferences.create(this, PREFERENCES_SCOPE); 950ce04b7a3f2c76452f855d082cd57d5e4cab9d69Steve McKay 9692ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector = new Injector<>( 970d83d32b66332034b17b327352693b125e9b3a05Tomasz Mikolajewski features, 9892ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay new Config(), 9992ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay ScopedPreferences.create(this, PREFERENCES_SCOPE), 10092ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay messages, 101b47b4b560c46336a0e6ba3e86db3f2d76b4b2bc3Garfield Tan DialogController.create(features, this, messages), 1020ce04b7a3f2c76452f855d082cd57d5e4cab9d69Steve McKay DocumentsApplication.getFileTypeLookup(this), 1030ce04b7a3f2c76452f855d082cd57d5e4cab9d69Steve McKay new ShortcutsUpdater(this, prefs)::update); 1046525a19f46eca7fbec21a71f833436823de03da3Steve McKay 105d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay super.onCreate(icicle); 106d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 10792ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay DocumentClipper clipper = DocumentsApplication.getDocumentClipper(this); 10892ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.selectionMgr = new SelectionManager(SelectionManager.MODE_MULTIPLE); 109047182631669608af946480c2545a10acb2ef1bfSteve McKay 11092ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.focusManager = new FocusManager( 11198f8c5f502e049a6b85439d773949cdbaa0f78aeSteve McKay mInjector.features, 112340ab17f468789bb507daeae116cf7940ba84b03Ben Lin mInjector.selectionMgr, 113340ab17f468789bb507daeae116cf7940ba84b03Ben Lin mDrawer, 114340ab17f468789bb507daeae116cf7940ba84b03Ben Lin this::focusSidebar, 115340ab17f468789bb507daeae116cf7940ba84b03Ben Lin getColor(R.color.accent_dark)); 116047182631669608af946480c2545a10acb2ef1bfSteve McKay 11792ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.menuManager = new MenuManager( 118710248d5ee766765b86fa36fe2ddd8d65f926755Steve McKay mInjector.features, 119e5d6ca2c7a32c826607d826bdc18f90ca8e8b7daSteve McKay mSearchManager, 120e5d6ca2c7a32c826607d826bdc18f90ca8e8b7daSteve McKay mState, 121e5d6ca2c7a32c826607d826bdc18f90ca8e8b7daSteve McKay new DirectoryDetails(this) { 122e5d6ca2c7a32c826607d826bdc18f90ca8e8b7daSteve McKay @Override 123e5d6ca2c7a32c826607d826bdc18f90ca8e8b7daSteve McKay public boolean hasItemsToPaste() { 12492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay return clipper.hasItemsToPaste(); 125e5d6ca2c7a32c826607d826bdc18f90ca8e8b7daSteve McKay } 126253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann }, 127253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann getApplicationContext(), 128253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann mInjector.selectionMgr, 1299bd4099ee27f8302a06fc66980079f29127318f8Jon Mann mProviders::getApplicationName, 130253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann mInjector.getModel()::getItemUri); 131bd9f05aa36bf19d8b34d0d73a59e9bd65d3d26ebSteve McKay 13292ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.actionModeController = new ActionModeController( 133bd9f05aa36bf19d8b34d0d73a59e9bd65d3d26ebSteve McKay this, 13492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.selectionMgr, 13592ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.menuManager, 13692ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.messages); 137bd9f05aa36bf19d8b34d0d73a59e9bd65d3d26ebSteve McKay 13892ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.actions = new ActionHandler<>( 139c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay this, 140c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay mState, 1419bd4099ee27f8302a06fc66980079f29127318f8Jon Mann mProviders, 14263bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mDocs, 14363bf8135243605949a3bb140167ef91f5c6ae2aeGarfield Tan mSearchManager, 144988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay ProviderExecutor::forAuthority, 14592ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.actionModeController, 14692ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay clipper, 14730d8c7988e15336d995e4b5033ba533a8333446fJon Mann DocumentsApplication.getClipStore(this), 148da2c0f0b075ad9f770182e706c2ec158989568a7Garfield Tan DocumentsApplication.getDragAndDropManager(this), 14930d8c7988e15336d995e4b5033ba533a8333446fJon Mann mInjector); 1501f199483b77166242c4648270eed601748eef1efSteve McKay 151e967033315ed64bca8c89d601d187fd12754f1fbGarfield Tan mInjector.searchManager = mSearchManager; 152e967033315ed64bca8c89d601d187fd12754f1fbGarfield Tan 15392ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mActivityInputHandler = 15492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay new ActivityInputHandler(mInjector.actions::deleteSelectedDocuments); 15598f8c5f502e049a6b85439d773949cdbaa0f78aeSteve McKay mSharedInputHandler = 1560902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin new SharedInputHandler( 1570902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin mInjector.focusManager, 1580902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin mInjector.selectionMgr, 1590902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin mInjector.searchManager::cancelSearch, 1600902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin this::popDir, 1610902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin mInjector.features); 16279ae3a7d0e6dd6d2e953709a092e83002941d48fBen Lin 1637d75f7bbd1693a33abb8de6b472ec1950e33eb8bGarfield Tan RootsFragment.show(getFragmentManager(), null); 164459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay 165cdbbbe05a66f70809669cb4f18ed7c42edb18426Tomasz Mikolajewski final Intent intent = getIntent(); 166739f94ba0dc9be264d9596dac551fd63082d2fddSteve McKay 16792ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.actions.initLocation(intent); 1687295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay 1697295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // Allow the activity to masquerade as another, so we can look both like 1707295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // Downloads and Files, but with only a single underlying activity. 1717295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay if (intent.hasExtra(LauncherActivity.TASK_LABEL_RES) 1727295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay && intent.hasExtra(LauncherActivity.TASK_ICON_RES)) { 1737295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay updateTaskDescription(intent); 1747295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay } 1757295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay 176988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay presentFileErrors(icicle, intent); 177988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay } 178cdbbbe05a66f70809669cb4f18ed7c42edb18426Tomasz Mikolajewski 1797295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // This is called in the intent contains label and icon resources. 1807295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // When that is true, the launcher activity has supplied them so we 1817295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // can adapt our presentation to how we were launched. 1827295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // Without this code, overlaying launcher_icon and launcher_label 1837295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // resources won't create a complete illusion of the activity being renamed. 1847295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // E.g. if we re-brand Files to Downloads by overlaying label and icon 1857295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // when the user tapped recents they'd see not "Downloads", but the 1867295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // underlying Activity description...Files. 1877295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // Alternate if we rename this activity, when launching other ways 1887295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // like when browsing files on a removable disk, the app would be 1897295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay // called Downloads, which is also not the desired behavior. 1907295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay private void updateTaskDescription(final Intent intent) { 1917295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay int labelRes = intent.getIntExtra(LauncherActivity.TASK_LABEL_RES, -1); 1927295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay assert(labelRes > -1); 1937295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay String label = getResources().getString(labelRes); 1947295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay 1957295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay int iconRes = intent.getIntExtra(LauncherActivity.TASK_ICON_RES, -1); 1967295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay assert(iconRes > -1); 1977295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay 198a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song Drawable drawable = getResources().getDrawable( 1997295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay iconRes, 2007295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay null // we don't care about theme, since the supplier should have handled that. 2017295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay ); 2027295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay 203a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song setTaskDescription(new TaskDescription(label, flattenDrawableToBitmap(drawable))); 204a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song } 205a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 206a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song // AdaptiveIconDrawable assumes that the consumer of the icon applies the shadow and 207a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song // recents assume that the provider of the task description handles these. Hence, 208a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song // we apply the shadow treatment same as Launcher3 implementation. 209a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song private Bitmap flattenDrawableToBitmap(Drawable d) { 210a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song // Percent of actual icon size 211a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song float ICON_SIZE_BLUR_FACTOR = 0.5f/48; 212a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song // Percent of actual icon size 213a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song float ICON_SIZE_KEY_SHADOW_DELTA_FACTOR = 1f/48; 214a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song int KEY_SHADOW_ALPHA = 61; 215a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song int AMBIENT_SHADOW_ALPHA = 30; 216a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song if (d instanceof BitmapDrawable) { 217a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song return ((BitmapDrawable) d).getBitmap(); 218a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song } else if (d instanceof AdaptiveIconDrawable) { 219a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song AdaptiveIconDrawable aid = (AdaptiveIconDrawable) d; 220a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song int iconSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size); 221a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song int shadowSize = Math.max(iconSize, aid.getIntrinsicHeight()); 222a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song aid.setBounds(0, 0, shadowSize, shadowSize); 223a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 224a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song float blur = ICON_SIZE_BLUR_FACTOR * shadowSize; 225a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song float keyShadowDistance = ICON_SIZE_KEY_SHADOW_DELTA_FACTOR * shadowSize; 226a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 227a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song int bitmapSize = (int) (shadowSize + 2 * blur + keyShadowDistance); 228a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song Bitmap shadow = Bitmap.createBitmap(bitmapSize, bitmapSize, Bitmap.Config.ARGB_8888); 229a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 230a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song Canvas canvas = new Canvas(shadow); 231a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song canvas.translate(blur + keyShadowDistance / 2, blur); 232a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 233a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 234a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song paint.setColor(Color.TRANSPARENT); 235a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 236a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song // Draw ambient shadow 237a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song paint.setShadowLayer(blur, 0, 0, AMBIENT_SHADOW_ALPHA << 24); 238a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song canvas.drawPath(aid.getIconMask(), paint); 239a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 240a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song // Draw key shadow 241a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song canvas.translate(0, keyShadowDistance); 242a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song paint.setShadowLayer(blur, 0, 0, KEY_SHADOW_ALPHA << 24); 243a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song canvas.drawPath(aid.getIconMask(), paint); 244a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 245a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song // Draw original drawable 246a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song aid.draw(canvas); 247a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song 248a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song canvas.setBitmap(null); 249a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song return shadow; 250a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song } 251a62e5047cb708a47c8b23aeb2be0951540a1d6e6Hyunyoung Song return null; 2527295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay } 2537295c484bfdd62066f6b49e225d0bf8af2cae19eSteve McKay 254988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay private void presentFileErrors(Bundle icicle, final Intent intent) { 255dd2b31c758e8d694867af58a425180689d25ead1Tomasz Mikolajewski final @DialogType int dialogType = intent.getIntExtra( 256dd2b31c758e8d694867af58a425180689d25ead1Tomasz Mikolajewski FileOperationService.EXTRA_DIALOG_TYPE, DIALOG_TYPE_UNKNOWN); 257cdbbbe05a66f70809669cb4f18ed7c42edb18426Tomasz Mikolajewski // DialogFragment takes care of restoring the dialog on configuration change. 258cdbbbe05a66f70809669cb4f18ed7c42edb18426Tomasz Mikolajewski // Only show it manually for the first time (icicle is null). 259dd2b31c758e8d694867af58a425180689d25ead1Tomasz Mikolajewski if (icicle == null && dialogType != DIALOG_TYPE_UNKNOWN) { 260dd2b31c758e8d694867af58a425180689d25ead1Tomasz Mikolajewski final int opType = intent.getIntExtra( 2614833477d7d42fa79ee42956bae4aebad77074e4bGarfield, Tan FileOperationService.EXTRA_OPERATION_TYPE, 262dd2b31c758e8d694867af58a425180689d25ead1Tomasz Mikolajewski FileOperationService.OPERATION_COPY); 26399f1dc3da6defec0596864934bfe76adc96a1d62Steve McKay final ArrayList<DocumentInfo> docList = 26499f1dc3da6defec0596864934bfe76adc96a1d62Steve McKay intent.getParcelableArrayListExtra(FileOperationService.EXTRA_FAILED_DOCS); 265664025e3eb9184817a1ebc21920c601466b907c1Tomasz Mikolajewski final ArrayList<Uri> uriList = 26699f1dc3da6defec0596864934bfe76adc96a1d62Steve McKay intent.getParcelableArrayListExtra(FileOperationService.EXTRA_FAILED_URIS); 267dd2b31c758e8d694867af58a425180689d25ead1Tomasz Mikolajewski OperationDialogFragment.show( 268cdbbbe05a66f70809669cb4f18ed7c42edb18426Tomasz Mikolajewski getFragmentManager(), 269dd2b31c758e8d694867af58a425180689d25ead1Tomasz Mikolajewski dialogType, 27099f1dc3da6defec0596864934bfe76adc96a1d62Steve McKay docList, 27199f1dc3da6defec0596864934bfe76adc96a1d62Steve McKay uriList, 272cdbbbe05a66f70809669cb4f18ed7c42edb18426Tomasz Mikolajewski mState.stack, 273c83baa0574ee9e34c0e06bda1ff08928d880ee36Steve McKay opType); 274d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } 275d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } 276d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 2770fbfc653868966da7fd6109b247974e0d87a2297Steve McKay @Override 27816e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay public void includeState(State state) { 279d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay final Intent intent = getIntent(); 2800574b18a7a95b29fab3cdb9ced6e5b46e24030feBen Kwa 28178ade2b9111c69a3cb169024646577f38136bbf7Garfield Tan // This is a remnant of old logic where we used to initialize accept MIME types in 2829bd4099ee27f8302a06fc66980079f29127318f8Jon Mann // BaseActivity. ProvidersAccess still rely on this being correctly initialized so we still have 28378ade2b9111c69a3cb169024646577f38136bbf7Garfield Tan // to initialize it in FilesActivity. 28478ade2b9111c69a3cb169024646577f38136bbf7Garfield Tan state.initAcceptMimes(intent, "*/*"); 285459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay state.action = State.ACTION_BROWSE; 2860574b18a7a95b29fab3cdb9ced6e5b46e24030feBen Kwa state.allowMultiple = true; 28764ac2519dc455a99cd1ac496cbf5cd76287dcce5Steve McKay 288459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay // Options specific to the DocumentsActivity. 2890af8afd3309538dec784ed0c9c35b252a8213123Steve McKay assert(!intent.hasExtra(Intent.EXTRA_LOCAL_ONLY)); 290d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } 291d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 292d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay @Override 293d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay protected void onPostCreate(Bundle savedInstanceState) { 294d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay super.onPostCreate(savedInstanceState); 295a8fa58d7449c0dd30e9701e611ae83175f2ad2f9Steve McKay // This check avoids a flicker from "Recents" to "Home". 296a8fa58d7449c0dd30e9701e611ae83175f2ad2f9Steve McKay // Only update action bar at this point if there is an active 2970930d4ca4b5161a22b0ddeca86c06533624ad610Dooper // search. Why? Because this avoid an early (undesired) load of 298a8fa58d7449c0dd30e9701e611ae83175f2ad2f9Steve McKay // the recents root...which is the default root in other activities. 299a8fa58d7449c0dd30e9701e611ae83175f2ad2f9Steve McKay // In Files app "Home" is the default, but it is loaded async. 30018d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay // update will be called once Home root is loaded. 301a8fa58d7449c0dd30e9701e611ae83175f2ad2f9Steve McKay // Except while searching we need this call to ensure the 3020930d4ca4b5161a22b0ddeca86c06533624ad610Dooper // search bits get laid out correctly. 303a8fa58d7449c0dd30e9701e611ae83175f2ad2f9Steve McKay if (mSearchManager.isSearching()) { 30418d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay mNavigator.update(); 305a8fa58d7449c0dd30e9701e611ae83175f2ad2f9Steve McKay } 306d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } 307d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 308d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay @Override 309459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay public void onResume() { 310459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay super.onResume(); 311459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay 312459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay final RootInfo root = getCurrentRoot(); 313459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay 314459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay // If we're browsing a specific root, and that root went away, then we 315459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay // have no reason to hang around. 316459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay // TODO: Rather than just disappearing, maybe we should inform 317459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay // the user what has happened, let them close us. Less surprising. 3189bd4099ee27f8302a06fc66980079f29127318f8Jon Mann if (mProviders.getRootBlocking(root.authority, root.rootId) == null) { 319459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay finish(); 320459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay } 321459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay } 322459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay 323459bc2b19ae24e3ad09b2945f21c8397177d5720Steve McKay @Override 32418d01e8d21376475cc9882dfcdce4a3d75f66690Steve McKay public String getDrawerTitle() { 32517f7e5891cbe86fc6cacae045a4edd3e41f8d5eeSteve McKay Intent intent = getIntent(); 32617f7e5891cbe86fc6cacae045a4edd3e41f8d5eeSteve McKay return (intent != null && intent.hasExtra(Intent.EXTRA_TITLE)) 32717f7e5891cbe86fc6cacae045a4edd3e41f8d5eeSteve McKay ? intent.getStringExtra(Intent.EXTRA_TITLE) 328a0b52655668ccbe3f12ca13ced4b34118a483783Steve McKay : getString(R.string.app_label); 329d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } 330d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 331d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay @Override 332d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay public boolean onPrepareOptionsMenu(Menu menu) { 333e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay super.onPrepareOptionsMenu(menu); 33492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.menuManager.updateOptionMenu(menu); 335e980927578d51373a53a3aa9531bc73fb773fff8Steve McKay return true; 336d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } 337d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 338d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay @Override 3391f199483b77166242c4648270eed601748eef1efSteve McKay public boolean onOptionsItemSelected(MenuItem item) { 34049be24c91d71d8f6fe6cb8eb6837b46468abffb5Jon Mann DirectoryFragment dir; 341f2c8b0dfe61deeedbed70931e0997a0b2f4eff45Steve McKay switch (item.getItemId()) { 342ff7f3aeec1b4fc7e0b8ddb0e8b6b6e105140f68eBen Lin case R.id.option_menu_create_dir: 3430af8afd3309538dec784ed0c9c35b252a8213123Steve McKay assert(canCreateDirectory()); 344ff7f3aeec1b4fc7e0b8ddb0e8b6b6e105140f68eBen Lin mInjector.actions.showCreateDirectoryDialog(); 3454972d71090b4e98951102ddd37fad95052525786Aga Wronska break; 346ff7f3aeec1b4fc7e0b8ddb0e8b6b6e105140f68eBen Lin case R.id.option_menu_new_window: 34792ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.actions.openInNewWindow(mState.stack); 3484972d71090b4e98951102ddd37fad95052525786Aga Wronska break; 349ff7f3aeec1b4fc7e0b8ddb0e8b6b6e105140f68eBen Lin case R.id.option_menu_settings: 35092ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.actions.openSettings(getCurrentRoot()); 3515668b866d52a4f8907474922dc9b1ba1b4db85a3Ben Lin break; 352ff7f3aeec1b4fc7e0b8ddb0e8b6b6e105140f68eBen Lin case R.id.option_menu_select_all: 35330d8c7988e15336d995e4b5033ba533a8333446fJon Mann mInjector.actions.selectAllFiles(); 35449be24c91d71d8f6fe6cb8eb6837b46468abffb5Jon Mann break; 3554972d71090b4e98951102ddd37fad95052525786Aga Wronska default: 3564972d71090b4e98951102ddd37fad95052525786Aga Wronska return super.onOptionsItemSelected(item); 3571f199483b77166242c4648270eed601748eef1efSteve McKay } 3584972d71090b4e98951102ddd37fad95052525786Aga Wronska return true; 3591f199483b77166242c4648270eed601748eef1efSteve McKay } 3601f199483b77166242c4648270eed601748eef1efSteve McKay 3611f199483b77166242c4648270eed601748eef1efSteve McKay @Override 362a86732316c8fe1694f4c1702cdd6c8e0faff4e18Ben Lin public void onProvideKeyboardShortcuts( 363a86732316c8fe1694f4c1702cdd6c8e0faff4e18Ben Lin List<KeyboardShortcutGroup> data, Menu menu, int deviceId) { 36492ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.menuManager.updateKeyboardShortcutsMenu(data, this::getString); 365a86732316c8fe1694f4c1702cdd6c8e0faff4e18Ben Lin } 366a86732316c8fe1694f4c1702cdd6c8e0faff4e18Ben Lin 367a86732316c8fe1694f4c1702cdd6c8e0faff4e18Ben Lin @Override 368988d8a354b00dce7e24deee187c08a4591956ac9Steve McKay public void refreshDirectory(@AnimationType int anim) { 369d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay final FragmentManager fm = getFragmentManager(); 370d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay final RootInfo root = getCurrentRoot(); 371d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay final DocumentInfo cwd = getCurrentDirectory(); 372d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 3730af8afd3309538dec784ed0c9c35b252a8213123Steve McKay assert(!mSearchManager.isSearching()); 374af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska 375e967033315ed64bca8c89d601d187fd12754f1fbGarfield Tan if (mState.stack.isRecents()) { 376d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay DirectoryFragment.showRecentsOpen(fm, anim); 377d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } else { 378af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska // Normal boring directory 379af5ace5d5e3a273b151e012206efd029c2872b59Aga Wronska DirectoryFragment.showDirectory(fm, root, cwd, anim); 380d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } 381d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay } 382d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay 383d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay @Override 384351a749751bc501c9d7c0f03ee5b542f0e7a7d7cSteve McKay public void onDocumentsPicked(List<DocumentInfo> docs) { 385351a749751bc501c9d7c0f03ee5b542f0e7a7d7cSteve McKay throw new UnsupportedOperationException(); 386351a749751bc501c9d7c0f03ee5b542f0e7a7d7cSteve McKay } 387351a749751bc501c9d7c0f03ee5b542f0e7a7d7cSteve McKay 388351a749751bc501c9d7c0f03ee5b542f0e7a7d7cSteve McKay @Override 389eed2f4ec78227b5e173ff667a5517637a91b9a30Steve McKay public void onDocumentPicked(DocumentInfo doc) { 390d22cc1852ed3e028a37d713e41c57286d2e4c9f2Tomasz Mikolajewski throw new UnsupportedOperationException(); 391be4e38b3113224d59cb1a2d4a8d29324019afb00Tomasz Mikolajewski } 392be4e38b3113224d59cb1a2d4a8d29324019afb00Tomasz Mikolajewski 393804133e4ca98ffa168cd547793054b594cf6d9ccGarfield, Tan @Override 39416e0c1fcf2be1ac7daafa6cb2c1c97d751ca3e66Steve McKay public void onDirectoryCreated(DocumentInfo doc) { 39581afd7f587176e7d63f00d533b1258dfec84bf5cBen Lin assert(doc.isDirectory()); 39692ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.focusManager.focusDocument(doc.documentId); 39781afd7f587176e7d63f00d533b1258dfec84bf5cBen Lin } 39881afd7f587176e7d63f00d533b1258dfec84bf5cBen Lin 399aa66c43df01033ccb957bfd1d513945676866f4cBen Lin @CallSuper 400aa66c43df01033ccb957bfd1d513945676866f4cBen Lin @Override 401aa66c43df01033ccb957bfd1d513945676866f4cBen Lin public boolean onKeyDown(int keyCode, KeyEvent event) { 402047182631669608af946480c2545a10acb2ef1bfSteve McKay return mActivityInputHandler.onKeyDown(keyCode, event) 4030902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin || mSharedInputHandler.onKeyDown( 4040902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin keyCode, 4050902f07dec9cfb0bd5d7c9c6222b433b91bf2051Ben Lin event) 406047182631669608af946480c2545a10acb2ef1bfSteve McKay || super.onKeyDown(keyCode, event); 407aa66c43df01033ccb957bfd1d513945676866f4cBen Lin } 408aa66c43df01033ccb957bfd1d513945676866f4cBen Lin 409d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay @Override 4100599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKay public boolean onKeyShortcut(int keyCode, KeyEvent event) { 4110599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKay DirectoryFragment dir; 412d4800817c434cb77ab03a2fd061da897a05cb933Steve McKay // TODO: All key events should be statically bound using alphabeticShortcut. 413d4800817c434cb77ab03a2fd061da897a05cb933Steve McKay // But not working. 4140599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKay switch (keyCode) { 4150599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKay case KeyEvent.KEYCODE_A: 41630d8c7988e15336d995e4b5033ba533a8333446fJon Mann mInjector.actions.selectAllFiles(); 4170599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKay return true; 418ff4d5846f8de51d51b87116cd07e559d75de2642Ben Lin case KeyEvent.KEYCODE_X: 41992ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.actions.cutToClipboard(); 420ff4d5846f8de51d51b87116cd07e559d75de2642Ben Lin return true; 4211f199483b77166242c4648270eed601748eef1efSteve McKay case KeyEvent.KEYCODE_C: 42292ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay mInjector.actions.copyToClipboard(); 4236035b3cc3b6b298ff8065b2ed55da651e6950802Steve McKay return true; 4246035b3cc3b6b298ff8065b2ed55da651e6950802Steve McKay case KeyEvent.KEYCODE_V: 425d4800817c434cb77ab03a2fd061da897a05cb933Steve McKay dir = getDirectoryFragment(); 426d4800817c434cb77ab03a2fd061da897a05cb933Steve McKay if (dir != null) { 427d4800817c434cb77ab03a2fd061da897a05cb933Steve McKay dir.pasteFromClipboard(); 428d4800817c434cb77ab03a2fd061da897a05cb933Steve McKay } 4296035b3cc3b6b298ff8065b2ed55da651e6950802Steve McKay return true; 4306035b3cc3b6b298ff8065b2ed55da651e6950802Steve McKay default: 4316035b3cc3b6b298ff8065b2ed55da651e6950802Steve McKay return super.onKeyShortcut(keyCode, event); 4320599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKay } 4330599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKay } 4340599a443b9bb4fd2ff8c6c6b95f94ba8f6ed3c9bSteve McKay 435b68dd223b2623c22793f5dcd0f658de0aa92f80dSteve McKay @Override 43692ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay public Injector<ActionHandler<FilesActivity>> getInjector() { 43792ae43d5d22331aad83e1a4302a7e1975f66354eSteve McKay return mInjector; 438c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKay } 439d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay} 440