Loading packages/DocumentsUI/res/layout/activity.xml +1 −1 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,7 @@ <ListView <ListView android:id="@+id/roots_list" android:id="@+id/roots_list" android:layout_width="300dp" android:layout_width="250dp" android:layout_height="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:layout_gravity="start" android:background="#fff" /> android:background="#fff" /> Loading packages/DocumentsUI/res/values/strings.xml +2 −0 Original line number Original line Diff line number Diff line Loading @@ -39,4 +39,6 @@ <string name="save_error">Failed to save document</string> <string name="save_error">Failed to save document</string> <string name="root_recent">Recent</string> </resources> </resources> packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +91 −79 Original line number Original line Diff line number Diff line Loading @@ -21,13 +21,10 @@ import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.FragmentTransaction; import android.app.LoaderManager.LoaderCallbacks; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.Context; import android.content.CursorLoader; import android.content.Loader; import android.content.Loader; import android.database.Cursor; import android.net.Uri; import android.net.Uri; import android.os.Bundle; import android.os.Bundle; import android.provider.DocumentsContract; import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; import android.text.format.DateUtils; import android.text.format.DateUtils; import android.util.SparseBooleanArray; import android.util.SparseBooleanArray; import android.view.ActionMode; import android.view.ActionMode; Loading @@ -41,17 +38,20 @@ import android.widget.AbsListView; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener; import android.widget.CursorAdapter; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.GridView; import android.widget.ImageView; import android.widget.ImageView; import android.widget.ListView; import android.widget.ListView; import android.widget.TextView; import android.widget.TextView; import com.android.documentsui.DocumentsActivity.DisplayState; import com.android.documentsui.DocumentsActivity.DisplayState; import com.android.documentsui.DocumentsActivity.Document; import com.android.documentsui.model.Document; import com.android.internal.util.Predicate; import com.google.android.collect.Lists; import com.google.android.collect.Lists; import java.util.ArrayList; import java.util.ArrayList; import java.util.Comparator; import java.util.List; /** /** * Display the documents inside a single directory. * Display the documents inside a single directory. Loading @@ -59,23 +59,21 @@ import java.util.ArrayList; public class DirectoryFragment extends Fragment { public class DirectoryFragment extends Fragment { // TODO: show storage backend in item views when requested // TODO: show storage backend in item views when requested // TODO: apply sort order locally // TODO: apply MIME filtering locally private ListView mListView; private ListView mListView; private GridView mGridView; private GridView mGridView; private AbsListView mCurrentView; private AbsListView mCurrentView; private static final int TYPE_NORMAL = 1; public static final int TYPE_NORMAL = 1; private static final int TYPE_SEARCH = 2; public static final int TYPE_SEARCH = 2; private static final int TYPE_RECENT_OPEN = 3; public static final int TYPE_RECENT_OPEN = 3; private static final int TYPE_RECENT_CREATE = 4; public static final int TYPE_RECENT_CREATE = 4; private int mType = TYPE_NORMAL; private int mType = TYPE_NORMAL; private DocumentsAdapter mAdapter; private DocumentsAdapter mAdapter; private LoaderCallbacks<Cursor> mCallbacks; private LoaderCallbacks<List<Document>> mCallbacks; private static final String EXTRA_URI = "uri"; private static final String EXTRA_URI = "uri"; Loading @@ -93,6 +91,11 @@ public class DirectoryFragment extends Fragment { ft.commitAllowingStateLoss(); ft.commitAllowingStateLoss(); } } public static DirectoryFragment get(FragmentManager fm) { // TODO: deal with multiple directories shown at once return (DirectoryFragment) fm.findFragmentById(R.id.directory); } @Override @Override public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); Loading @@ -114,7 +117,7 @@ public class DirectoryFragment extends Fragment { mGridView.setOnItemClickListener(mItemListener); mGridView.setOnItemClickListener(mItemListener); mGridView.setMultiChoiceModeListener(mMultiListener); mGridView.setMultiChoiceModeListener(mMultiListener); mAdapter = new DocumentsAdapter(context); mAdapter = new DocumentsAdapter(); updateMode(); updateMode(); final Uri uri = getArguments().getParcelable(EXTRA_URI); final Uri uri = getArguments().getParcelable(EXTRA_URI); Loading @@ -129,18 +132,10 @@ public class DirectoryFragment extends Fragment { mType = TYPE_NORMAL; mType = TYPE_NORMAL; } } mCallbacks = new LoaderCallbacks<Cursor>() { mCallbacks = new LoaderCallbacks<List<Document>>() { @Override @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { public Loader<List<Document>> onCreateLoader(int id, Bundle args) { final DisplayState state = getDisplayState(DirectoryFragment.this); final DisplayState state = getDisplayState(DirectoryFragment.this); final String sortOrder; if (state.sortBy == DisplayState.SORT_BY_NAME) { sortOrder = DocumentColumns.DISPLAY_NAME + " ASC"; } else if (state.sortBy == DisplayState.SORT_BY_DATE) { sortOrder = DocumentColumns.LAST_MODIFIED + " DESC"; } else { sortOrder = null; } final Uri contentsUri; final Uri contentsUri; if (mType == TYPE_NORMAL) { if (mType == TYPE_NORMAL) { Loading @@ -149,17 +144,29 @@ public class DirectoryFragment extends Fragment { contentsUri = uri; contentsUri = uri; } } return new CursorLoader(context, contentsUri, null, null, null, sortOrder); final Predicate<Document> filter = new MimePredicate(state.acceptMimes); final Comparator<Document> sortOrder; if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN || mType == TYPE_RECENT_CREATE) { sortOrder = new Document.DateComparator(); } else if (state.sortOrder == DisplayState.SORT_ORDER_NAME) { sortOrder = new Document.NameComparator(); } else { throw new IllegalArgumentException("Unknown sort order " + state.sortOrder); } return new DirectoryLoader(context, contentsUri, mType, filter, sortOrder); } } @Override @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { public void onLoadFinished(Loader<List<Document>> loader, List<Document> data) { mAdapter.swapCursor(data); mAdapter.swapDocuments(data); } } @Override @Override public void onLoaderReset(Loader<Cursor> loader) { public void onLoaderReset(Loader<List<Document>> loader) { mAdapter.swapCursor(null); mAdapter.swapDocuments(null); } } }; }; Loading Loading @@ -243,16 +250,16 @@ public class DirectoryFragment extends Fragment { } } } } public void updateSortBy() { public void updateSortOrder() { getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); mListView.smoothScrollToPosition(0); mGridView.smoothScrollToPosition(0); } } private OnItemClickListener mItemListener = new OnItemClickListener() { private OnItemClickListener mItemListener = new OnItemClickListener() { @Override @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Cursor cursor = (Cursor) mAdapter.getItem(position); final Document doc = mAdapter.getItem(position); final Uri uri = getArguments().getParcelable(EXTRA_URI); final Document doc = Document.fromCursor(uri, cursor); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); } } }; }; Loading @@ -279,8 +286,8 @@ public class DirectoryFragment extends Fragment { final int size = checked.size(); final int size = checked.size(); for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) { if (checked.valueAt(i)) { if (checked.valueAt(i)) { final Cursor cursor = (Cursor) mAdapter.getItem(checked.keyAt(i)); final Document doc = mAdapter.getItem(checked.keyAt(i)); docs.add(Document.fromCursor(uri, cursor)); docs.add(doc); } } } } Loading @@ -300,11 +307,9 @@ public class DirectoryFragment extends Fragment { public void onItemCheckedStateChanged( public void onItemCheckedStateChanged( ActionMode mode, int position, long id, boolean checked) { ActionMode mode, int position, long id, boolean checked) { if (checked) { if (checked) { final Cursor cursor = (Cursor) mAdapter.getItem(position); final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); // Directories cannot be checked // Directories cannot be checked if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { final Document doc = mAdapter.getItem(position); if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(doc.mimeType)) { mCurrentView.setItemChecked(position, false); mCurrentView.setItemChecked(position, false); } } } } Loading @@ -318,61 +323,68 @@ public class DirectoryFragment extends Fragment { return ((DocumentsActivity) fragment.getActivity()).getDisplayState(); return ((DocumentsActivity) fragment.getActivity()).getDisplayState(); } } private class DocumentsAdapter extends CursorAdapter { private class DocumentsAdapter extends BaseAdapter { public DocumentsAdapter(Context context) { private List<Document> mDocuments; super(context, null, false); public DocumentsAdapter() { } public void swapDocuments(List<Document> documents) { mDocuments = documents; notifyDataSetChanged(); } } @Override @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) { final Context context = parent.getContext(); if (convertView == null) { final LayoutInflater inflater = LayoutInflater.from(context); final LayoutInflater inflater = LayoutInflater.from(context); final DisplayState state = getDisplayState(DirectoryFragment.this); final DisplayState state = getDisplayState(DirectoryFragment.this); if (state.mode == DisplayState.MODE_LIST) { if (state.mode == DisplayState.MODE_LIST) { return inflater.inflate(R.layout.item_doc_list, parent, false); convertView = inflater.inflate(R.layout.item_doc_list, parent, false); } else if (state.mode == DisplayState.MODE_GRID) { } else if (state.mode == DisplayState.MODE_GRID) { return inflater.inflate(R.layout.item_doc_grid, parent, false); convertView = inflater.inflate(R.layout.item_doc_grid, parent, false); } else { } else { throw new IllegalStateException(); throw new IllegalStateException(); } } } } @Override final Document doc = getItem(position); public void bindView(View view, Context context, Cursor cursor) { final TextView title = (TextView) view.findViewById(android.R.id.title); final TextView summary = (TextView) view.findViewById(android.R.id.summary); final ImageView icon = (ImageView) view.findViewById(android.R.id.icon); final String docId = getCursorString(cursor, DocumentColumns.DOC_ID); final TextView title = (TextView) convertView.findViewById(android.R.id.title); final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME); final TextView summary = (TextView) convertView.findViewById(android.R.id.summary); final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon); final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); final Uri uri = getArguments().getParcelable(EXTRA_URI); if (doc.isThumbnailSupported()) { if ((flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0) { // TODO: load thumbnails async final Uri childUri = DocumentsContract.buildDocumentUri(uri, docId); icon.setImageURI(doc.uri); icon.setImageURI(childUri); } else { } else { icon.setImageDrawable(DocumentsActivity.resolveDocumentIcon( icon.setImageDrawable(DocumentsActivity.resolveDocumentIcon( context, uri.getAuthority(), mimeType)); context, doc.uri.getAuthority(), doc.mimeType)); } } title.setText(displayName); title.setText(doc.displayName); if (summary != null) { if (summary != null) { summary.setText(DateUtils.getRelativeTimeSpanString(lastModified)); summary.setText(DateUtils.getRelativeTimeSpanString(doc.lastModified)); } } } return convertView; } } public static String getCursorString(Cursor cursor, String columnName) { @Override return cursor.getString(cursor.getColumnIndex(columnName)); public int getCount() { return mDocuments != null ? mDocuments.size() : 0; } } public static long getCursorLong(Cursor cursor, String columnName) { @Override return cursor.getLong(cursor.getColumnIndex(columnName)); public Document getItem(int position) { return mDocuments.get(position); } } public static int getCursorInt(Cursor cursor, String columnName) { @Override return cursor.getInt(cursor.getColumnIndex(columnName)); public long getItemId(int position) { return getItem(position).uri.hashCode(); } } } } } packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java 0 → 100644 +90 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2013 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; import static com.android.documentsui.DirectoryFragment.TYPE_NORMAL; import static com.android.documentsui.DirectoryFragment.TYPE_RECENT_OPEN; import static com.android.documentsui.DirectoryFragment.TYPE_SEARCH; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.CancellationSignal; import com.android.documentsui.model.Document; import com.android.internal.util.Predicate; import com.google.android.collect.Lists; import libcore.io.IoUtils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class DirectoryLoader extends UriDerivativeLoader<List<Document>> { private final int mType; private Predicate<Document> mFilter; private Comparator<Document> mSortOrder; public DirectoryLoader(Context context, Uri uri, int type, Predicate<Document> filter, Comparator<Document> sortOrder) { super(context, uri); mType = type; mFilter = filter; mSortOrder = sortOrder; } @Override public List<Document> loadInBackground(Uri uri, CancellationSignal signal) { final ArrayList<Document> result = Lists.newArrayList(); // TODO: send selection and sorting hints to backend final ContentResolver resolver = getContext().getContentResolver(); final Cursor cursor = resolver.query(uri, null, null, null, null, signal); try { while (cursor != null && cursor.moveToNext()) { final Document doc; switch (mType) { case TYPE_NORMAL: case TYPE_SEARCH: doc = Document.fromDirectoryCursor(uri, cursor); break; case TYPE_RECENT_OPEN: doc = Document.fromRecentOpenCursor(resolver, cursor); break; default: throw new IllegalArgumentException("Unknown type"); } if (mFilter == null || mFilter.apply(doc)) { result.add(doc); } } } finally { IoUtils.closeQuietly(cursor); } if (mSortOrder != null) { Collections.sort(result, mSortOrder); } return result; } } packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +81 −257 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/DocumentsUI/res/layout/activity.xml +1 −1 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,7 @@ <ListView <ListView android:id="@+id/roots_list" android:id="@+id/roots_list" android:layout_width="300dp" android:layout_width="250dp" android:layout_height="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:layout_gravity="start" android:background="#fff" /> android:background="#fff" /> Loading
packages/DocumentsUI/res/values/strings.xml +2 −0 Original line number Original line Diff line number Diff line Loading @@ -39,4 +39,6 @@ <string name="save_error">Failed to save document</string> <string name="save_error">Failed to save document</string> <string name="root_recent">Recent</string> </resources> </resources>
packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +91 −79 Original line number Original line Diff line number Diff line Loading @@ -21,13 +21,10 @@ import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.FragmentTransaction; import android.app.LoaderManager.LoaderCallbacks; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.Context; import android.content.CursorLoader; import android.content.Loader; import android.content.Loader; import android.database.Cursor; import android.net.Uri; import android.net.Uri; import android.os.Bundle; import android.os.Bundle; import android.provider.DocumentsContract; import android.provider.DocumentsContract; import android.provider.DocumentsContract.DocumentColumns; import android.text.format.DateUtils; import android.text.format.DateUtils; import android.util.SparseBooleanArray; import android.util.SparseBooleanArray; import android.view.ActionMode; import android.view.ActionMode; Loading @@ -41,17 +38,20 @@ import android.widget.AbsListView; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AbsListView.MultiChoiceModeListener; import android.widget.AdapterView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemClickListener; import android.widget.CursorAdapter; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.GridView; import android.widget.ImageView; import android.widget.ImageView; import android.widget.ListView; import android.widget.ListView; import android.widget.TextView; import android.widget.TextView; import com.android.documentsui.DocumentsActivity.DisplayState; import com.android.documentsui.DocumentsActivity.DisplayState; import com.android.documentsui.DocumentsActivity.Document; import com.android.documentsui.model.Document; import com.android.internal.util.Predicate; import com.google.android.collect.Lists; import com.google.android.collect.Lists; import java.util.ArrayList; import java.util.ArrayList; import java.util.Comparator; import java.util.List; /** /** * Display the documents inside a single directory. * Display the documents inside a single directory. Loading @@ -59,23 +59,21 @@ import java.util.ArrayList; public class DirectoryFragment extends Fragment { public class DirectoryFragment extends Fragment { // TODO: show storage backend in item views when requested // TODO: show storage backend in item views when requested // TODO: apply sort order locally // TODO: apply MIME filtering locally private ListView mListView; private ListView mListView; private GridView mGridView; private GridView mGridView; private AbsListView mCurrentView; private AbsListView mCurrentView; private static final int TYPE_NORMAL = 1; public static final int TYPE_NORMAL = 1; private static final int TYPE_SEARCH = 2; public static final int TYPE_SEARCH = 2; private static final int TYPE_RECENT_OPEN = 3; public static final int TYPE_RECENT_OPEN = 3; private static final int TYPE_RECENT_CREATE = 4; public static final int TYPE_RECENT_CREATE = 4; private int mType = TYPE_NORMAL; private int mType = TYPE_NORMAL; private DocumentsAdapter mAdapter; private DocumentsAdapter mAdapter; private LoaderCallbacks<Cursor> mCallbacks; private LoaderCallbacks<List<Document>> mCallbacks; private static final String EXTRA_URI = "uri"; private static final String EXTRA_URI = "uri"; Loading @@ -93,6 +91,11 @@ public class DirectoryFragment extends Fragment { ft.commitAllowingStateLoss(); ft.commitAllowingStateLoss(); } } public static DirectoryFragment get(FragmentManager fm) { // TODO: deal with multiple directories shown at once return (DirectoryFragment) fm.findFragmentById(R.id.directory); } @Override @Override public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); Loading @@ -114,7 +117,7 @@ public class DirectoryFragment extends Fragment { mGridView.setOnItemClickListener(mItemListener); mGridView.setOnItemClickListener(mItemListener); mGridView.setMultiChoiceModeListener(mMultiListener); mGridView.setMultiChoiceModeListener(mMultiListener); mAdapter = new DocumentsAdapter(context); mAdapter = new DocumentsAdapter(); updateMode(); updateMode(); final Uri uri = getArguments().getParcelable(EXTRA_URI); final Uri uri = getArguments().getParcelable(EXTRA_URI); Loading @@ -129,18 +132,10 @@ public class DirectoryFragment extends Fragment { mType = TYPE_NORMAL; mType = TYPE_NORMAL; } } mCallbacks = new LoaderCallbacks<Cursor>() { mCallbacks = new LoaderCallbacks<List<Document>>() { @Override @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { public Loader<List<Document>> onCreateLoader(int id, Bundle args) { final DisplayState state = getDisplayState(DirectoryFragment.this); final DisplayState state = getDisplayState(DirectoryFragment.this); final String sortOrder; if (state.sortBy == DisplayState.SORT_BY_NAME) { sortOrder = DocumentColumns.DISPLAY_NAME + " ASC"; } else if (state.sortBy == DisplayState.SORT_BY_DATE) { sortOrder = DocumentColumns.LAST_MODIFIED + " DESC"; } else { sortOrder = null; } final Uri contentsUri; final Uri contentsUri; if (mType == TYPE_NORMAL) { if (mType == TYPE_NORMAL) { Loading @@ -149,17 +144,29 @@ public class DirectoryFragment extends Fragment { contentsUri = uri; contentsUri = uri; } } return new CursorLoader(context, contentsUri, null, null, null, sortOrder); final Predicate<Document> filter = new MimePredicate(state.acceptMimes); final Comparator<Document> sortOrder; if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN || mType == TYPE_RECENT_CREATE) { sortOrder = new Document.DateComparator(); } else if (state.sortOrder == DisplayState.SORT_ORDER_NAME) { sortOrder = new Document.NameComparator(); } else { throw new IllegalArgumentException("Unknown sort order " + state.sortOrder); } return new DirectoryLoader(context, contentsUri, mType, filter, sortOrder); } } @Override @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { public void onLoadFinished(Loader<List<Document>> loader, List<Document> data) { mAdapter.swapCursor(data); mAdapter.swapDocuments(data); } } @Override @Override public void onLoaderReset(Loader<Cursor> loader) { public void onLoaderReset(Loader<List<Document>> loader) { mAdapter.swapCursor(null); mAdapter.swapDocuments(null); } } }; }; Loading Loading @@ -243,16 +250,16 @@ public class DirectoryFragment extends Fragment { } } } } public void updateSortBy() { public void updateSortOrder() { getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); mListView.smoothScrollToPosition(0); mGridView.smoothScrollToPosition(0); } } private OnItemClickListener mItemListener = new OnItemClickListener() { private OnItemClickListener mItemListener = new OnItemClickListener() { @Override @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { final Cursor cursor = (Cursor) mAdapter.getItem(position); final Document doc = mAdapter.getItem(position); final Uri uri = getArguments().getParcelable(EXTRA_URI); final Document doc = Document.fromCursor(uri, cursor); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); ((DocumentsActivity) getActivity()).onDocumentPicked(doc); } } }; }; Loading @@ -279,8 +286,8 @@ public class DirectoryFragment extends Fragment { final int size = checked.size(); final int size = checked.size(); for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) { if (checked.valueAt(i)) { if (checked.valueAt(i)) { final Cursor cursor = (Cursor) mAdapter.getItem(checked.keyAt(i)); final Document doc = mAdapter.getItem(checked.keyAt(i)); docs.add(Document.fromCursor(uri, cursor)); docs.add(doc); } } } } Loading @@ -300,11 +307,9 @@ public class DirectoryFragment extends Fragment { public void onItemCheckedStateChanged( public void onItemCheckedStateChanged( ActionMode mode, int position, long id, boolean checked) { ActionMode mode, int position, long id, boolean checked) { if (checked) { if (checked) { final Cursor cursor = (Cursor) mAdapter.getItem(position); final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); // Directories cannot be checked // Directories cannot be checked if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { final Document doc = mAdapter.getItem(position); if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(doc.mimeType)) { mCurrentView.setItemChecked(position, false); mCurrentView.setItemChecked(position, false); } } } } Loading @@ -318,61 +323,68 @@ public class DirectoryFragment extends Fragment { return ((DocumentsActivity) fragment.getActivity()).getDisplayState(); return ((DocumentsActivity) fragment.getActivity()).getDisplayState(); } } private class DocumentsAdapter extends CursorAdapter { private class DocumentsAdapter extends BaseAdapter { public DocumentsAdapter(Context context) { private List<Document> mDocuments; super(context, null, false); public DocumentsAdapter() { } public void swapDocuments(List<Document> documents) { mDocuments = documents; notifyDataSetChanged(); } } @Override @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) { final Context context = parent.getContext(); if (convertView == null) { final LayoutInflater inflater = LayoutInflater.from(context); final LayoutInflater inflater = LayoutInflater.from(context); final DisplayState state = getDisplayState(DirectoryFragment.this); final DisplayState state = getDisplayState(DirectoryFragment.this); if (state.mode == DisplayState.MODE_LIST) { if (state.mode == DisplayState.MODE_LIST) { return inflater.inflate(R.layout.item_doc_list, parent, false); convertView = inflater.inflate(R.layout.item_doc_list, parent, false); } else if (state.mode == DisplayState.MODE_GRID) { } else if (state.mode == DisplayState.MODE_GRID) { return inflater.inflate(R.layout.item_doc_grid, parent, false); convertView = inflater.inflate(R.layout.item_doc_grid, parent, false); } else { } else { throw new IllegalStateException(); throw new IllegalStateException(); } } } } @Override final Document doc = getItem(position); public void bindView(View view, Context context, Cursor cursor) { final TextView title = (TextView) view.findViewById(android.R.id.title); final TextView summary = (TextView) view.findViewById(android.R.id.summary); final ImageView icon = (ImageView) view.findViewById(android.R.id.icon); final String docId = getCursorString(cursor, DocumentColumns.DOC_ID); final TextView title = (TextView) convertView.findViewById(android.R.id.title); final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME); final TextView summary = (TextView) convertView.findViewById(android.R.id.summary); final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon); final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); final Uri uri = getArguments().getParcelable(EXTRA_URI); if (doc.isThumbnailSupported()) { if ((flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0) { // TODO: load thumbnails async final Uri childUri = DocumentsContract.buildDocumentUri(uri, docId); icon.setImageURI(doc.uri); icon.setImageURI(childUri); } else { } else { icon.setImageDrawable(DocumentsActivity.resolveDocumentIcon( icon.setImageDrawable(DocumentsActivity.resolveDocumentIcon( context, uri.getAuthority(), mimeType)); context, doc.uri.getAuthority(), doc.mimeType)); } } title.setText(displayName); title.setText(doc.displayName); if (summary != null) { if (summary != null) { summary.setText(DateUtils.getRelativeTimeSpanString(lastModified)); summary.setText(DateUtils.getRelativeTimeSpanString(doc.lastModified)); } } } return convertView; } } public static String getCursorString(Cursor cursor, String columnName) { @Override return cursor.getString(cursor.getColumnIndex(columnName)); public int getCount() { return mDocuments != null ? mDocuments.size() : 0; } } public static long getCursorLong(Cursor cursor, String columnName) { @Override return cursor.getLong(cursor.getColumnIndex(columnName)); public Document getItem(int position) { return mDocuments.get(position); } } public static int getCursorInt(Cursor cursor, String columnName) { @Override return cursor.getInt(cursor.getColumnIndex(columnName)); public long getItemId(int position) { return getItem(position).uri.hashCode(); } } } } }
packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java 0 → 100644 +90 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2013 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; import static com.android.documentsui.DirectoryFragment.TYPE_NORMAL; import static com.android.documentsui.DirectoryFragment.TYPE_RECENT_OPEN; import static com.android.documentsui.DirectoryFragment.TYPE_SEARCH; import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.CancellationSignal; import com.android.documentsui.model.Document; import com.android.internal.util.Predicate; import com.google.android.collect.Lists; import libcore.io.IoUtils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class DirectoryLoader extends UriDerivativeLoader<List<Document>> { private final int mType; private Predicate<Document> mFilter; private Comparator<Document> mSortOrder; public DirectoryLoader(Context context, Uri uri, int type, Predicate<Document> filter, Comparator<Document> sortOrder) { super(context, uri); mType = type; mFilter = filter; mSortOrder = sortOrder; } @Override public List<Document> loadInBackground(Uri uri, CancellationSignal signal) { final ArrayList<Document> result = Lists.newArrayList(); // TODO: send selection and sorting hints to backend final ContentResolver resolver = getContext().getContentResolver(); final Cursor cursor = resolver.query(uri, null, null, null, null, signal); try { while (cursor != null && cursor.moveToNext()) { final Document doc; switch (mType) { case TYPE_NORMAL: case TYPE_SEARCH: doc = Document.fromDirectoryCursor(uri, cursor); break; case TYPE_RECENT_OPEN: doc = Document.fromRecentOpenCursor(resolver, cursor); break; default: throw new IllegalArgumentException("Unknown type"); } if (mFilter == null || mFilter.apply(doc)) { result.add(doc); } } } finally { IoUtils.closeQuietly(cursor); } if (mSortOrder != null) { Collections.sort(result, mSortOrder); } return result; } }
packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +81 −257 File changed.Preview size limit exceeded, changes collapsed. Show changes