diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java index 108d5e831c279..cc173b5f372e2 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -184,7 +184,7 @@ public class DirectoryFragment extends Fragment { private Point mThumbSize; private DocumentsAdapter mAdapter; private LoaderCallbacks mCallbacks; - private FragmentTuner mFragmentTuner; + private FragmentTuner mTuner; private DocumentClipper mClipper; // These are lazily initialized. private LinearLayoutManager mListLayout; @@ -319,7 +319,7 @@ public class DirectoryFragment extends Fragment { super.onActivityCreated(savedInstanceState); final Context context = getActivity(); - final State state = getDisplayState(DirectoryFragment.this); + final State state = getDisplayState(); final RootInfo root = getArguments().getParcelable(EXTRA_ROOT); final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); @@ -381,7 +381,7 @@ public class DirectoryFragment extends Fragment { mType = getArguments().getInt(EXTRA_TYPE); mStateKey = buildStateKey(root, doc); - mFragmentTuner = FragmentTuner.pick(state); + mTuner = FragmentTuner.pick(state); mClipper = new DocumentClipper(context); if (mType == TYPE_RECENT_OPEN) { @@ -485,7 +485,7 @@ public class DirectoryFragment extends Fragment { return; } - CopyService.start(getActivity(), getDisplayState(this).selectedDocumentsForCopy, + CopyService.start(getActivity(), getDisplayState().selectedDocumentsForCopy, (DocumentStack) data.getParcelableExtra(Shared.EXTRA_STACK), data.getIntExtra(CopyService.EXTRA_TRANSFER_MODE, CopyService.TRANSFER_MODE_COPY)); } @@ -524,7 +524,7 @@ public class DirectoryFragment extends Fragment { checkNotNull(cursor, "Cursor cannot be null."); final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); - if (isDocumentEnabled(docMimeType, docFlags)) { + if (mTuner.isDocumentEnabled(docMimeType, docFlags)) { final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor); ((BaseActivity) getActivity()).onDocumentPicked(doc, mModel); mSelectionManager.clearSelection(); @@ -540,7 +540,7 @@ public class DirectoryFragment extends Fragment { // Remember last scroll location final SparseArray container = new SparseArray(); getView().saveHierarchyState(container); - final State state = getDisplayState(this); + final State state = getDisplayState(); state.dirState.put(mStateKey, container); } @@ -562,7 +562,7 @@ public class DirectoryFragment extends Fragment { public void onUserModeChanged() { final ContentResolver resolver = getActivity().getContentResolver(); - final State state = getDisplayState(this); + final State state = getDisplayState(); final RootInfo root = getArguments().getParcelable(EXTRA_ROOT); final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); @@ -591,7 +591,7 @@ public class DirectoryFragment extends Fragment { } private void updateDisplayState() { - final State state = getDisplayState(this); + final State state = getDisplayState(); if (mLastMode == state.derivedMode && mLastShowSize == state.showSize) return; mLastMode = state.derivedMode; @@ -665,13 +665,13 @@ public class DirectoryFragment extends Fragment { @Override public boolean onBeforeItemStateChange(int position, boolean selected) { - // Directories cannot be checked if (selected) { final Cursor cursor = mModel.getItem(position); checkNotNull(cursor, "Cursor cannot be null."); final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); - return isDocumentEnabled(docMimeType, docFlags); + return mTuner.canSelectType(docMimeType) + && mTuner.isDocumentEnabled(docMimeType, docFlags); } return true; } @@ -743,7 +743,7 @@ public class DirectoryFragment extends Fragment { private void updateActionMenu() { checkNotNull(mMenu); // Delegate update logic to our owning action, since specialized logic is desired. - mFragmentTuner.updateActionMenu(mMenu, mType, mNoDeleteCount == 0); + mTuner.updateActionMenu(mMenu, mType, mNoDeleteCount == 0); Menus.disableHiddenItems(mMenu); } @@ -915,7 +915,7 @@ public class DirectoryFragment extends Fragment { new GetDocumentsTask() { @Override void onDocumentsReady(List docs) { - getDisplayState(DirectoryFragment.this).selectedDocumentsForCopy = docs; + getDisplayState().selectedDocumentsForCopy = docs; boolean directoryCopy = false; for (DocumentInfo info : docs) { @@ -931,8 +931,8 @@ public class DirectoryFragment extends Fragment { }.execute(selected); } - private static State getDisplayState(Fragment fragment) { - return ((BaseActivity) fragment.getActivity()).getDisplayState(); + private State getDisplayState() { + return ((BaseActivity) getActivity()).getDisplayState(); } // Provide a reference to the views for each data item @@ -1027,7 +1027,7 @@ public class DirectoryFragment extends Fragment { @Override public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) { - final State state = getDisplayState(DirectoryFragment.this); + final State state = getDisplayState(); final LayoutInflater inflater = LayoutInflater.from(getContext()); View item = null; switch (state.derivedMode) { @@ -1070,8 +1070,7 @@ public class DirectoryFragment extends Fragment { public void onBindViewHolder(DocumentHolder holder, int position) { final Context context = getContext(); - final State state = getDisplayState(DirectoryFragment.this); - final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); + final State state = getDisplayState(); final RootsCache roots = DocumentsApplication.getRootsCache(context); final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache( context, mThumbSize); @@ -1121,7 +1120,7 @@ public class DirectoryFragment extends Fragment { || MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, docMimeType); final boolean showThumbnail = supportsThumbnail && allowThumbnail && !mSvelteRecents; - final boolean enabled = isDocumentEnabled(docMimeType, docFlags); + final boolean enabled = mTuner.isDocumentEnabled(docMimeType, docFlags); final float iconAlpha = (state.derivedMode == MODE_LIST && !enabled) ? 0.5f : 1f; boolean cacheHit = false; @@ -1330,22 +1329,6 @@ public class DirectoryFragment extends Fragment { } } - private boolean isDocumentEnabled(String docMimeType, int docFlags) { - final State state = getDisplayState(DirectoryFragment.this); - - // Directories are always enabled - if (Document.MIME_TYPE_DIR.equals(docMimeType)) { - return true; - } - - // Read-only files are disabled when creating - if (state.action == ACTION_CREATE && (docFlags & Document.FLAG_SUPPORTS_WRITE) == 0) { - return false; - } - - return MimePredicate.mimeMatches(state.acceptMimes, docMimeType); - } - private void copyFromClipboard() { new AsyncTask>() { @@ -1393,7 +1376,7 @@ public class DirectoryFragment extends Fragment { return; } - final DocumentStack curStack = getDisplayState(DirectoryFragment.this).stack; + final DocumentStack curStack = getDisplayState().stack; DocumentStack tmpStack = new DocumentStack(); if (destination != null) { tmpStack.push(destination); @@ -1590,7 +1573,7 @@ public class DirectoryFragment extends Fragment { if (docs.size() == 1) { final DocumentInfo doc = docs.get(0); return getDocumentIcon(getActivity(), doc.authority, doc.documentId, - doc.mimeType, doc.icon, getDisplayState(this)); + doc.mimeType, doc.icon, getDisplayState()); } return getActivity().getDrawable(R.drawable.ic_doc_generic); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java index 7e9bbe2023d60..a0ff165d76ec2 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java @@ -17,39 +17,104 @@ package com.android.documentsui.dirlist; import static com.android.documentsui.State.ACTION_BROWSE; +import static com.android.documentsui.State.ACTION_CREATE; +import static com.android.documentsui.State.ACTION_GET_CONTENT; import static com.android.documentsui.State.ACTION_MANAGE; +import static com.android.documentsui.State.ACTION_OPEN; +import static com.android.documentsui.State.ACTION_OPEN_TREE; import static com.android.internal.util.Preconditions.checkArgument; -import android.os.SystemProperties; -import android.view.Menu; -import android.view.MenuItem; - import com.android.documentsui.Menus; +import com.android.documentsui.MimePredicate; import com.android.documentsui.R; import com.android.documentsui.State; +import android.os.SystemProperties; +import android.provider.DocumentsContract.Document; +import android.view.Menu; +import android.view.MenuItem; + /** * Providers support for specializing the DirectoryFragment to the "host" Activity. * Feel free to expand the role of this class to handle other specializations. */ public abstract class FragmentTuner { + + final State mState; + + public FragmentTuner(State state) { + mState = state; + } + public static FragmentTuner pick(State state) { switch (state.action) { case ACTION_BROWSE: - return new FilesTuner(); + return new FilesTuner(state); case ACTION_MANAGE: - return new ManageTuner(); + return new DownloadsTuner(state); default: - return new DocumentsTuner(); + return new DocumentsTuner(state); } } + public abstract void updateActionMenu(Menu menu, int dirType, boolean canDelete); + // Subtly different from isDocumentEnabled. The reason may be illuminated as follows. + // A folder is enabled such that it may be double clicked, even in settings + // when the folder itself cannot be selected. This may also be true of container types. + public boolean canSelectType(String docMimeType) { + return true; + } + + public boolean isDocumentEnabled(String docMimeType, int docFlags) { + if (isDirectory(docMimeType)) { + return true; + } + + return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType); + } + /** * Provides support for Platform specific specializations of DirectoryFragment. */ private static final class DocumentsTuner extends FragmentTuner { + + public DocumentsTuner(State state) { + super(state); + } + + @Override + public boolean canSelectType(String docMimeType) { + switch (mState.action) { + case ACTION_OPEN: + case ACTION_CREATE: + case ACTION_GET_CONTENT: + return !isDirectory(docMimeType); + case ACTION_OPEN_TREE: + // In this case nothing *ever* is selectable...the expected user behavior is + // they navigate *into* a folder, then click a confirmation button indicating + // that the current directory is the directory they are picking. + return false; + } + return true; + } + + @Override + public boolean isDocumentEnabled(String docMimeType, int docFlags) { + // Directories are always enabled + if (isDirectory(docMimeType)) { + return true; + } + + // Read-only files are disabled when creating + if (mState.action == ACTION_CREATE && (docFlags & Document.FLAG_SUPPORTS_WRITE) == 0) { + return false; + } + + return MimePredicate.mimeMatches(mState.acceptMimes, docMimeType); + } + @Override public void updateActionMenu(Menu menu, int dirType, boolean canDelete) { @@ -77,7 +142,11 @@ public abstract class FragmentTuner { /** * Provides support for Platform specific specializations of DirectoryFragment. */ - private static final class ManageTuner extends FragmentTuner { + private static final class DownloadsTuner extends FragmentTuner { + + public DownloadsTuner(State state) { + super(state); + } @Override public void updateActionMenu(Menu menu, int dirType, boolean canDelete) { @@ -107,6 +176,11 @@ public abstract class FragmentTuner { * Provides support for Files activity specific specializations of DirectoryFragment. */ private static final class FilesTuner extends FragmentTuner { + + public FilesTuner(State state) { + super(state); + } + @Override public void updateActionMenu(Menu menu, int dirType, boolean canDelete) { @@ -124,4 +198,8 @@ public abstract class FragmentTuner { Menus.disableHiddenItems(menu, copy, paste); } } + + private static boolean isDirectory(String mimeType) { + return Document.MIME_TYPE_DIR.equals(mimeType); + } }