blob: 8ef8910339013e80a91ff8f90a3dcd0b1efee25b [file] [log] [blame]
Steve McKayd3f6f142015-10-27 15:57:53 -07001/*
2 * Copyright (C) 2015 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.dirlist;
18
19import static com.android.documentsui.State.ACTION_BROWSE;
Steve McKayf69502c2015-11-09 17:38:35 +090020import static com.android.documentsui.State.ACTION_CREATE;
21import static com.android.documentsui.State.ACTION_GET_CONTENT;
Steve McKayd3f6f142015-10-27 15:57:53 -070022import static com.android.documentsui.State.ACTION_MANAGE;
Steve McKayf69502c2015-11-09 17:38:35 +090023import static com.android.documentsui.State.ACTION_OPEN;
24import static com.android.documentsui.State.ACTION_OPEN_TREE;
Steve McKayd3f6f142015-10-27 15:57:53 -070025import static com.android.internal.util.Preconditions.checkArgument;
26
Steve McKayaa15dae2016-02-09 16:17:24 -080027import android.content.Context;
Steve McKayaa15dae2016-02-09 16:17:24 -080028import android.provider.DocumentsContract.Document;
Steve McKayaa15dae2016-02-09 16:17:24 -080029import android.view.Menu;
30import android.view.MenuItem;
31
Steve McKayc95d87c2016-02-23 14:34:50 -080032import com.android.documentsui.BaseActivity;
Steve McKayd3f6f142015-10-27 15:57:53 -070033import com.android.documentsui.Menus;
Steve McKayf69502c2015-11-09 17:38:35 +090034import com.android.documentsui.MimePredicate;
Steve McKayd3f6f142015-10-27 15:57:53 -070035import com.android.documentsui.R;
36import com.android.documentsui.State;
Steve McKayaa15dae2016-02-09 16:17:24 -080037import com.android.documentsui.dirlist.DirectoryFragment.ResultType;
Steve McKayf69502c2015-11-09 17:38:35 +090038
Steve McKayd3f6f142015-10-27 15:57:53 -070039/**
40 * Providers support for specializing the DirectoryFragment to the "host" Activity.
41 * Feel free to expand the role of this class to handle other specializations.
42 */
43public abstract class FragmentTuner {
Steve McKayf69502c2015-11-09 17:38:35 +090044
Steve McKayaa15dae2016-02-09 16:17:24 -080045 final Context mContext;
Steve McKayf69502c2015-11-09 17:38:35 +090046 final State mState;
47
Steve McKayaa15dae2016-02-09 16:17:24 -080048 public FragmentTuner(Context context, State state) {
49 mContext = context;
Steve McKayf69502c2015-11-09 17:38:35 +090050 mState = state;
51 }
52
Steve McKayaa15dae2016-02-09 16:17:24 -080053 public static FragmentTuner pick(Context context, State state) {
Steve McKayd3f6f142015-10-27 15:57:53 -070054 switch (state.action) {
55 case ACTION_BROWSE:
Steve McKayaa15dae2016-02-09 16:17:24 -080056 return new FilesTuner(context, state);
Steve McKayd3f6f142015-10-27 15:57:53 -070057 case ACTION_MANAGE:
Steve McKayaa15dae2016-02-09 16:17:24 -080058 return new DownloadsTuner(context, state);
Steve McKayd3f6f142015-10-27 15:57:53 -070059 default:
Steve McKayaa15dae2016-02-09 16:17:24 -080060 return new DocumentsTuner(context, state);
Steve McKayd3f6f142015-10-27 15:57:53 -070061 }
62 }
63
Steve McKayf69502c2015-11-09 17:38:35 +090064
Steve McKay27d20a32016-02-22 18:38:09 -080065 public abstract void updateActionMenu(
66 Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename);
Steve McKayd3f6f142015-10-27 15:57:53 -070067
Steve McKayf69502c2015-11-09 17:38:35 +090068 // Subtly different from isDocumentEnabled. The reason may be illuminated as follows.
69 // A folder is enabled such that it may be double clicked, even in settings
70 // when the folder itself cannot be selected. This may also be true of container types.
Tomasz Mikolajewskia8057a92015-11-16 11:41:28 +090071 public boolean canSelectType(String docMimeType, int docFlags) {
Steve McKayf69502c2015-11-09 17:38:35 +090072 return true;
73 }
74
75 public boolean isDocumentEnabled(String docMimeType, int docFlags) {
76 if (isDirectory(docMimeType)) {
77 return true;
78 }
79
80 return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
81 }
82
Aga Wronska893390b2016-02-17 13:50:42 -080083 abstract void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch);
Steve McKayaa15dae2016-02-09 16:17:24 -080084
Steve McKayd3f6f142015-10-27 15:57:53 -070085 /**
86 * Provides support for Platform specific specializations of DirectoryFragment.
87 */
88 private static final class DocumentsTuner extends FragmentTuner {
Steve McKayf69502c2015-11-09 17:38:35 +090089
Steve McKayaa15dae2016-02-09 16:17:24 -080090 public DocumentsTuner(Context context, State state) {
91 super(context, state);
Steve McKayf69502c2015-11-09 17:38:35 +090092 }
93
94 @Override
Tomasz Mikolajewskia8057a92015-11-16 11:41:28 +090095 public boolean canSelectType(String docMimeType, int docFlags) {
96 if (!isDocumentEnabled(docMimeType, docFlags)) {
97 return false;
Steve McKayf69502c2015-11-09 17:38:35 +090098 }
Tomasz Mikolajewskia8057a92015-11-16 11:41:28 +090099
100 if (isDirectory(docMimeType)) {
101 return false;
102 }
103
104 if (mState.action == ACTION_OPEN_TREE) {
105 // In this case nothing *ever* is selectable...the expected user behavior is
106 // they navigate *into* a folder, then click a confirmation button indicating
107 // that the current directory is the directory they are picking.
108 return false;
109 }
110
Steve McKayf69502c2015-11-09 17:38:35 +0900111 return true;
112 }
113
114 @Override
115 public boolean isDocumentEnabled(String docMimeType, int docFlags) {
Tomasz Mikolajewskia8057a92015-11-16 11:41:28 +0900116 // Directories are always enabled.
Steve McKayf69502c2015-11-09 17:38:35 +0900117 if (isDirectory(docMimeType)) {
118 return true;
119 }
120
Tomasz Mikolajewskia8057a92015-11-16 11:41:28 +0900121 switch (mState.action) {
122 case ACTION_CREATE:
123 // Read-only files are disabled when creating.
124 if ((docFlags & Document.FLAG_SUPPORTS_WRITE) == 0) {
125 return false;
126 }
127 case ACTION_OPEN:
128 case ACTION_GET_CONTENT:
129 final boolean isVirtual = (docFlags & Document.FLAG_VIRTUAL_DOCUMENT) != 0;
130 if (isVirtual && mState.openableOnly) {
131 return false;
132 }
Steve McKayf69502c2015-11-09 17:38:35 +0900133 }
134
135 return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType);
136 }
137
Steve McKayd3f6f142015-10-27 15:57:53 -0700138 @Override
Steve McKay27d20a32016-02-22 18:38:09 -0800139 public void updateActionMenu(
140 Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename) {
Steve McKayd3f6f142015-10-27 15:57:53 -0700141
Steve McKay27d20a32016-02-22 18:38:09 -0800142 MenuItem open = menu.findItem(R.id.menu_open);
143 MenuItem share = menu.findItem(R.id.menu_share);
144 MenuItem delete = menu.findItem(R.id.menu_delete);
145 MenuItem rename = menu.findItem(R.id.menu_rename);
Steve McKayd3f6f142015-10-27 15:57:53 -0700146
147 open.setVisible(true);
148 share.setVisible(false);
149 delete.setVisible(false);
Aga Wronska3b327ef2016-01-20 16:32:33 -0800150 rename.setVisible(false);
Steve McKayd3f6f142015-10-27 15:57:53 -0700151 }
Steve McKayaa15dae2016-02-09 16:17:24 -0800152
153 @Override
Aga Wronska893390b2016-02-17 13:50:42 -0800154 void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {
Steve McKayc95d87c2016-02-23 14:34:50 -0800155 // When launched into empty root, open drawer.
156 if (model.isEmpty() && !mState.hasInitialLocationChanged() && !isSearch) {
157 // This noops on layouts without drawer, so no need to guard.
158 ((BaseActivity) mContext).setRootsDrawerOpen(true);
Steve McKayaa15dae2016-02-09 16:17:24 -0800159 }
160 }
Steve McKayd3f6f142015-10-27 15:57:53 -0700161 }
162
163 /**
164 * Provides support for Platform specific specializations of DirectoryFragment.
165 */
Steve McKayf69502c2015-11-09 17:38:35 +0900166 private static final class DownloadsTuner extends FragmentTuner {
167
Steve McKayaa15dae2016-02-09 16:17:24 -0800168 public DownloadsTuner(Context context, State state) {
169 super(context, state);
Steve McKayf69502c2015-11-09 17:38:35 +0900170 }
Steve McKayd3f6f142015-10-27 15:57:53 -0700171
172 @Override
Steve McKay27d20a32016-02-22 18:38:09 -0800173 public void updateActionMenu(
174 Menu menu, @ResultType int resultType, boolean canDelete, boolean canRename) {
175 checkArgument(resultType != DirectoryFragment.TYPE_RECENT_OPEN);
Steve McKayd3f6f142015-10-27 15:57:53 -0700176
Steve McKay27d20a32016-02-22 18:38:09 -0800177 MenuItem open = menu.findItem(R.id.menu_open);
178 MenuItem delete = menu.findItem(R.id.menu_delete);
179 MenuItem copyTo = menu.findItem(R.id.menu_copy_to);
180 MenuItem moveTo = menu.findItem(R.id.menu_move_to);
181 MenuItem rename = menu.findItem(R.id.menu_rename);
182 MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
Steve McKayd3f6f142015-10-27 15:57:53 -0700183
184 open.setVisible(false);
Steve McKayd3f6f142015-10-27 15:57:53 -0700185 delete.setVisible(canDelete);
Steve McKay27d20a32016-02-22 18:38:09 -0800186 copy.setEnabled(true); // to clipboard
Steve McKayd3f6f142015-10-27 15:57:53 -0700187 copyTo.setVisible(true);
188 copyTo.setEnabled(true);
Steve McKay27d20a32016-02-22 18:38:09 -0800189 moveTo.setVisible(true);
190 moveTo.setEnabled(true);
Aga Wronska3b327ef2016-01-20 16:32:33 -0800191 rename.setVisible(false);
Steve McKayd3f6f142015-10-27 15:57:53 -0700192 }
Steve McKayaa15dae2016-02-09 16:17:24 -0800193
194 @Override
Aga Wronska893390b2016-02-17 13:50:42 -0800195 void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {}
Steve McKayd3f6f142015-10-27 15:57:53 -0700196 }
197
198 /**
199 * Provides support for Files activity specific specializations of DirectoryFragment.
200 */
201 private static final class FilesTuner extends FragmentTuner {
Steve McKayf69502c2015-11-09 17:38:35 +0900202
Steve McKayaa15dae2016-02-09 16:17:24 -0800203 public FilesTuner(Context context, State state) {
204 super(context, state);
Steve McKayf69502c2015-11-09 17:38:35 +0900205 }
206
Steve McKayd3f6f142015-10-27 15:57:53 -0700207 @Override
Steve McKay27d20a32016-02-22 18:38:09 -0800208 public void updateActionMenu(
209 Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename) {
Steve McKayd3f6f142015-10-27 15:57:53 -0700210
211 MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard);
212 MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard);
213 copy.setEnabled(dirType != DirectoryFragment.TYPE_RECENT_OPEN);
214
Aga Wronska3b327ef2016-01-20 16:32:33 -0800215 MenuItem rename = menu.findItem(R.id.menu_rename);
216 rename.setVisible(true);
217 rename.setEnabled(canRename);
218
Steve McKayd3f6f142015-10-27 15:57:53 -0700219 menu.findItem(R.id.menu_share).setVisible(true);
220 menu.findItem(R.id.menu_delete).setVisible(canDelete);
Steve McKayd3f6f142015-10-27 15:57:53 -0700221 menu.findItem(R.id.menu_open).setVisible(false);
222 menu.findItem(R.id.menu_copy_to).setVisible(true);
223 menu.findItem(R.id.menu_move_to).setVisible(true);
Steve McKay27d20a32016-02-22 18:38:09 -0800224 menu.findItem(R.id.menu_move_to).setEnabled(canDelete);
Steve McKayd3f6f142015-10-27 15:57:53 -0700225
226 Menus.disableHiddenItems(menu, copy, paste);
227 }
Steve McKayaa15dae2016-02-09 16:17:24 -0800228
229 @Override
Aga Wronska893390b2016-02-17 13:50:42 -0800230 void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {
Steve McKayaa15dae2016-02-09 16:17:24 -0800231 // When launched into empty root, open drawer.
Steve McKayc95d87c2016-02-23 14:34:50 -0800232 if (model.isEmpty() && !mState.hasInitialLocationChanged() && !isSearch) {
Steve McKayaa15dae2016-02-09 16:17:24 -0800233 // This noops on layouts without drawer, so no need to guard.
Steve McKayc95d87c2016-02-23 14:34:50 -0800234 ((BaseActivity) mContext).setRootsDrawerOpen(true);
Steve McKayaa15dae2016-02-09 16:17:24 -0800235 }
Steve McKayaa15dae2016-02-09 16:17:24 -0800236 }
Steve McKayd3f6f142015-10-27 15:57:53 -0700237 }
Steve McKayf69502c2015-11-09 17:38:35 +0900238
239 private static boolean isDirectory(String mimeType) {
240 return Document.MIME_TYPE_DIR.equals(mimeType);
241 }
Steve McKayd3f6f142015-10-27 15:57:53 -0700242}