Loading packages/DocumentsUI/AndroidManifest.xml +11 −1 Original line number Diff line number Diff line Loading @@ -12,11 +12,21 @@ <intent-filter android:priority="100"> <action android:name="android.intent.action.OPEN_DOCUMENT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="*/*" /> </intent-filter> <intent-filter android:priority="100"> <action android:name="android.intent.action.CREATE_DOCUMENT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="*/*" /> </intent-filter> </activity> <!-- TODO: remove when we have real clients --> <activity android:name=".TestActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> Loading packages/DocumentsUI/res/menu/directory.xml +6 −3 Original line number Diff line number Diff line Loading @@ -18,13 +18,16 @@ <item android:id="@+id/menu_grid" android:title="@string/menu_grid" android:icon="@drawable/ic_menu_grid" /> android:icon="@drawable/ic_menu_grid" android:showAsAction="ifRoom" /> <item android:id="@+id/menu_list" android:title="@string/menu_list" android:icon="@drawable/ic_menu_list" /> android:icon="@drawable/ic_menu_list" android:showAsAction="ifRoom" /> <item android:id="@+id/menu_sort" android:title="@string/menu_sort" android:icon="@drawable/ic_menu_sort" /> android:icon="@drawable/ic_menu_sort" android:showAsAction="ifRoom" /> </menu> packages/DocumentsUI/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -30,4 +30,7 @@ <string name="mode_selected_count"><xliff:g id="count" example="3">%1$d</xliff:g> selected</string> <string name="sort_name">Name</string> <string name="sort_date">Date modified</string> </resources> packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +80 −31 Original line number Diff line number Diff line Loading @@ -16,12 +16,17 @@ package com.android.documentsui; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.CursorLoader; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Loader; import android.database.Cursor; import android.net.Uri; Loading @@ -47,6 +52,7 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.android.documentsui.DocumentsActivity.DisplayState; import com.android.documentsui.DocumentsActivity.Document; import com.google.android.collect.Lists; Loading @@ -58,7 +64,8 @@ import java.util.ArrayList; public class DirectoryFragment extends Fragment { // TODO: show storage backend in item views when requested // TODO: implement sorting dialog private static final String TAG_SORT = "sort"; private ListView mListView; private GridView mGridView; Loading @@ -71,20 +78,12 @@ public class DirectoryFragment extends Fragment { private int mFlags; private static final String EXTRA_URI = "uri"; private static final String EXTRA_MODE = "display_mode"; private static final String EXTRA_ALLOW_MULTIPLE = "allow_multiple"; private static final int MODE_LIST = 1; private static final int MODE_GRID = 2; private static final int LOADER_DOCUMENTS = 2; public static void show( FragmentManager fm, Uri uri, String displayName, boolean allowMultiple) { public static void show(FragmentManager fm, Uri uri, String displayName) { final Bundle args = new Bundle(); args.putParcelable(EXTRA_URI, uri); args.putInt(EXTRA_MODE, MODE_LIST); args.putBoolean(EXTRA_ALLOW_MULTIPLE, allowMultiple); final DirectoryFragment fragment = new DirectoryFragment(); fragment.setArguments(args); Loading Loading @@ -127,8 +126,18 @@ public class DirectoryFragment extends Fragment { mCallbacks = new LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { 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 = DocumentsContract.buildContentsUri(uri); return new CursorLoader(context, contentsUri, null, null, null, null); return new CursorLoader(context, contentsUri, null, null, null, sortOrder); } @Override Loading Loading @@ -170,21 +179,27 @@ public class DirectoryFragment extends Fragment { @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); final int mode = getMode(); menu.findItem(R.id.menu_grid).setVisible(mode != MODE_GRID); menu.findItem(R.id.menu_list).setVisible(mode != MODE_LIST); final DisplayState state = getDisplayState(this); menu.findItem(R.id.menu_grid).setVisible(state.mode != DisplayState.MODE_GRID); menu.findItem(R.id.menu_list).setVisible(state.mode != DisplayState.MODE_LIST); } @Override public boolean onOptionsItemSelected(MenuItem item) { final DisplayState state = getDisplayState(this); final int id = item.getItemId(); if (id == R.id.menu_grid) { getArguments().putInt(EXTRA_MODE, MODE_GRID); state.mode = DisplayState.MODE_GRID; updateMode(); getFragmentManager().invalidateOptionsMenu(); return true; } else if (id == R.id.menu_list) { getArguments().putInt(EXTRA_MODE, MODE_LIST); state.mode = DisplayState.MODE_LIST; updateMode(); getFragmentManager().invalidateOptionsMenu(); return true; } else if (id == R.id.menu_sort) { SortFragment.show(this); return true; } else { return super.onOptionsItemSelected(item); Loading @@ -192,19 +207,19 @@ public class DirectoryFragment extends Fragment { } private void updateMode() { final int mode = getMode(); final DisplayState state = getDisplayState(this); mListView.setVisibility(mode == MODE_LIST ? View.VISIBLE : View.GONE); mGridView.setVisibility(mode == MODE_GRID ? View.VISIBLE : View.GONE); mListView.setVisibility(state.mode == DisplayState.MODE_LIST ? View.VISIBLE : View.GONE); mGridView.setVisibility(state.mode == DisplayState.MODE_GRID ? View.VISIBLE : View.GONE); final int choiceMode; if (getArguments().getBoolean(EXTRA_ALLOW_MULTIPLE)) { if (state.allowMultiple) { choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL; } else { choiceMode = ListView.CHOICE_MODE_NONE; } if (mode == MODE_GRID) { if (state.mode == DisplayState.MODE_GRID) { mListView.setAdapter(null); mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); mGridView.setAdapter(mAdapter); Loading @@ -212,15 +227,21 @@ public class DirectoryFragment extends Fragment { mGridView.setNumColumns(GridView.AUTO_FIT); mGridView.setChoiceMode(choiceMode); mCurrentView = mGridView; } else { } else if (state.mode == DisplayState.MODE_LIST) { mGridView.setAdapter(null); mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE); mListView.setAdapter(mAdapter); mListView.setChoiceMode(choiceMode); mCurrentView = mListView; } else { throw new IllegalStateException(); } } private void updateSortBy() { getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); } private OnItemClickListener mItemListener = new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Loading Loading @@ -288,12 +309,8 @@ public class DirectoryFragment extends Fragment { } }; private boolean getSupportsCreate() { return (mFlags & DocumentsContract.FLAG_SUPPORTS_CREATE) != 0; } private int getMode() { return getArguments().getInt(EXTRA_MODE, MODE_LIST); private static DisplayState getDisplayState(Fragment fragment) { return ((DocumentsActivity) fragment.getActivity()).getDisplayState(); } private class DocumentsAdapter extends CursorAdapter { Loading @@ -304,10 +321,10 @@ public class DirectoryFragment extends Fragment { @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { final LayoutInflater inflater = LayoutInflater.from(context); final int mode = getMode(); if (mode == MODE_LIST) { final DisplayState state = getDisplayState(DirectoryFragment.this); if (state.mode == DisplayState.MODE_LIST) { return inflater.inflate(R.layout.item_doc_list, parent, false); } else if (mode == MODE_GRID) { } else if (state.mode == DisplayState.MODE_GRID) { return inflater.inflate(R.layout.item_doc_grid, parent, false); } else { throw new IllegalStateException(); Loading Loading @@ -341,6 +358,38 @@ public class DirectoryFragment extends Fragment { } } public static class SortFragment extends DialogFragment { public static void show(DirectoryFragment parent) { if (!parent.isAdded()) return; final SortFragment dialog = new SortFragment(); dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), TAG_SORT); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Context context = getActivity(); final DisplayState state = getDisplayState(this); final AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.menu_sort); builder.setSingleChoiceItems(new CharSequence[] { getText(R.string.sort_name), getText(R.string.sort_date), }, state.sortBy, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { state.sortBy = which; ((DirectoryFragment) getTargetFragment()).updateSortBy(); dismiss(); } }); return builder.create(); } } private static int getDocumentFlags(Context context, Uri uri) { final Cursor cursor = context.getContentResolver().query(uri, new String[] { DocumentColumns.FLAGS }, null, null, null); Loading packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +62 −18 Original line number Diff line number Diff line Loading @@ -55,13 +55,14 @@ public class DocumentsActivity extends Activity { // TODO: fragment to show recently opened documents // TODO: pull actionbar icon from current backend private static final int MODE_OPEN = 1; private static final int MODE_CREATE = 2; private static final int ACTION_OPEN = 1; private static final int ACTION_CREATE = 2; private int mMode; private boolean mAllowMultiple; private int mAction; private String[] mAcceptMimes; private final DisplayState mDisplayState = new DisplayState(); private boolean mIgnoreNextNavigation; private Uri mCurrentDir; Loading @@ -74,11 +75,11 @@ public class DocumentsActivity extends Activity { final Intent intent = getIntent(); final String action = intent.getAction(); if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) { mMode = MODE_OPEN; mAllowMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); mAction = ACTION_OPEN; mDisplayState.allowMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) { mMode = MODE_CREATE; mAllowMultiple = false; mAction = ACTION_CREATE; mDisplayState.allowMultiple = false; } if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { Loading @@ -87,6 +88,12 @@ public class DocumentsActivity extends Activity { mAcceptMimes = new String[] { intent.getType() }; } if (mimeMatches("image/*", mAcceptMimes)) { mDisplayState.mode = DisplayState.MODE_GRID; } else { mDisplayState.mode = DisplayState.MODE_LIST; } setResult(Activity.RESULT_CANCELED); setContentView(R.layout.activity); Loading @@ -95,7 +102,7 @@ public class DocumentsActivity extends Activity { updateActionBar(); if (mMode == MODE_CREATE) { if (mAction == ACTION_CREATE) { final String mimeType = getIntent().getType(); final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE); SaveFragment.show(getFragmentManager(), mimeType, title); Loading @@ -120,9 +127,9 @@ public class DocumentsActivity extends Activity { actionBar.setDisplayShowHomeEnabled(false); actionBar.setDisplayHomeAsUpEnabled(false); if (mMode == MODE_OPEN) { if (mAction == ACTION_OPEN) { actionBar.setTitle(R.string.title_open); } else if (mMode == MODE_CREATE) { } else if (mAction == ACTION_CREATE) { actionBar.setTitle(R.string.title_save); } } Loading @@ -140,7 +147,7 @@ public class DocumentsActivity extends Activity { super.onPrepareOptionsMenu(menu); final MenuItem createDir = menu.findItem(R.id.menu_create_dir); createDir.setVisible(mMode == MODE_CREATE); createDir.setVisible(mAction == ACTION_CREATE); createDir.setEnabled(mCurrentSupportsCreate); return true; Loading Loading @@ -209,11 +216,15 @@ public class DocumentsActivity extends Activity { } }; public DisplayState getDisplayState() { return mDisplayState; } public void onDirectoryChanged(Uri uri, int flags) { mCurrentDir = uri; mCurrentSupportsCreate = (flags & DocumentsContract.FLAG_SUPPORTS_CREATE) != 0; if (mMode == MODE_CREATE) { if (mAction == ACTION_CREATE) { final FragmentManager fm = getFragmentManager(); SaveFragment.get(fm).setSaveEnabled(mCurrentSupportsCreate); } Loading @@ -225,18 +236,18 @@ public class DocumentsActivity extends Activity { final Uri uri = DocumentsContract.buildDocumentUri( info.authority, DocumentsContract.ROOT_GUID); final CharSequence displayName = info.loadLabel(getPackageManager()); DirectoryFragment.show(getFragmentManager(), uri, displayName.toString(), mAllowMultiple); DirectoryFragment.show(getFragmentManager(), uri, displayName.toString()); } public void onDocumentPicked(Document doc) { final FragmentManager fm = getFragmentManager(); if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(doc.mimeType)) { // Nested directory picked, recurse using new fragment DirectoryFragment.show(fm, doc.uri, doc.displayName, mAllowMultiple); } else if (mMode == MODE_OPEN) { DirectoryFragment.show(fm, doc.uri, doc.displayName); } else if (mAction == ACTION_OPEN) { // Explicit file picked, return onFinished(doc.uri); } else if (mMode == MODE_CREATE) { } else if (mAction == ACTION_CREATE) { // Overwrite current filename SaveFragment.get(fm).setDisplayName(doc.displayName); } Loading Loading @@ -274,7 +285,7 @@ public class DocumentsActivity extends Activity { intent.addFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION); if (mMode == MODE_CREATE) { if (mAction == ACTION_CREATE) { intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } Loading @@ -282,6 +293,18 @@ public class DocumentsActivity extends Activity { finish(); } public static class DisplayState { public int mode; public int sortBy; public boolean allowMultiple; public static final int MODE_LIST = 0; public static final int MODE_GRID = 1; public static final int SORT_BY_NAME = 0; public static final int SORT_BY_DATE = 1; } public static class Document { public Uri uri; public String mimeType; Loading @@ -297,6 +320,27 @@ public class DocumentsActivity extends Activity { } } public static boolean mimeMatches(String filter, String[] tests) { for (String test : tests) { if (mimeMatches(filter, test)) { return true; } } return false; } public static boolean mimeMatches(String filter, String test) { if (filter.equals(test)) { return true; } else if ("*/*".equals(filter)) { return true; } else if (filter.endsWith("/*")) { return filter.regionMatches(0, test, 0, filter.indexOf('/')); } else { return false; } } public static Drawable resolveDocumentIcon(Context context, String mimeType) { // TODO: allow backends to provide custom MIME icons if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { Loading Loading
packages/DocumentsUI/AndroidManifest.xml +11 −1 Original line number Diff line number Diff line Loading @@ -12,11 +12,21 @@ <intent-filter android:priority="100"> <action android:name="android.intent.action.OPEN_DOCUMENT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="*/*" /> </intent-filter> <intent-filter android:priority="100"> <action android:name="android.intent.action.CREATE_DOCUMENT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="*/*" /> </intent-filter> </activity> <!-- TODO: remove when we have real clients --> <activity android:name=".TestActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> Loading
packages/DocumentsUI/res/menu/directory.xml +6 −3 Original line number Diff line number Diff line Loading @@ -18,13 +18,16 @@ <item android:id="@+id/menu_grid" android:title="@string/menu_grid" android:icon="@drawable/ic_menu_grid" /> android:icon="@drawable/ic_menu_grid" android:showAsAction="ifRoom" /> <item android:id="@+id/menu_list" android:title="@string/menu_list" android:icon="@drawable/ic_menu_list" /> android:icon="@drawable/ic_menu_list" android:showAsAction="ifRoom" /> <item android:id="@+id/menu_sort" android:title="@string/menu_sort" android:icon="@drawable/ic_menu_sort" /> android:icon="@drawable/ic_menu_sort" android:showAsAction="ifRoom" /> </menu>
packages/DocumentsUI/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -30,4 +30,7 @@ <string name="mode_selected_count"><xliff:g id="count" example="3">%1$d</xliff:g> selected</string> <string name="sort_name">Name</string> <string name="sort_date">Date modified</string> </resources>
packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java +80 −31 Original line number Diff line number Diff line Loading @@ -16,12 +16,17 @@ package com.android.documentsui; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.CursorLoader; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Loader; import android.database.Cursor; import android.net.Uri; Loading @@ -47,6 +52,7 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import com.android.documentsui.DocumentsActivity.DisplayState; import com.android.documentsui.DocumentsActivity.Document; import com.google.android.collect.Lists; Loading @@ -58,7 +64,8 @@ import java.util.ArrayList; public class DirectoryFragment extends Fragment { // TODO: show storage backend in item views when requested // TODO: implement sorting dialog private static final String TAG_SORT = "sort"; private ListView mListView; private GridView mGridView; Loading @@ -71,20 +78,12 @@ public class DirectoryFragment extends Fragment { private int mFlags; private static final String EXTRA_URI = "uri"; private static final String EXTRA_MODE = "display_mode"; private static final String EXTRA_ALLOW_MULTIPLE = "allow_multiple"; private static final int MODE_LIST = 1; private static final int MODE_GRID = 2; private static final int LOADER_DOCUMENTS = 2; public static void show( FragmentManager fm, Uri uri, String displayName, boolean allowMultiple) { public static void show(FragmentManager fm, Uri uri, String displayName) { final Bundle args = new Bundle(); args.putParcelable(EXTRA_URI, uri); args.putInt(EXTRA_MODE, MODE_LIST); args.putBoolean(EXTRA_ALLOW_MULTIPLE, allowMultiple); final DirectoryFragment fragment = new DirectoryFragment(); fragment.setArguments(args); Loading Loading @@ -127,8 +126,18 @@ public class DirectoryFragment extends Fragment { mCallbacks = new LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { 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 = DocumentsContract.buildContentsUri(uri); return new CursorLoader(context, contentsUri, null, null, null, null); return new CursorLoader(context, contentsUri, null, null, null, sortOrder); } @Override Loading Loading @@ -170,21 +179,27 @@ public class DirectoryFragment extends Fragment { @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); final int mode = getMode(); menu.findItem(R.id.menu_grid).setVisible(mode != MODE_GRID); menu.findItem(R.id.menu_list).setVisible(mode != MODE_LIST); final DisplayState state = getDisplayState(this); menu.findItem(R.id.menu_grid).setVisible(state.mode != DisplayState.MODE_GRID); menu.findItem(R.id.menu_list).setVisible(state.mode != DisplayState.MODE_LIST); } @Override public boolean onOptionsItemSelected(MenuItem item) { final DisplayState state = getDisplayState(this); final int id = item.getItemId(); if (id == R.id.menu_grid) { getArguments().putInt(EXTRA_MODE, MODE_GRID); state.mode = DisplayState.MODE_GRID; updateMode(); getFragmentManager().invalidateOptionsMenu(); return true; } else if (id == R.id.menu_list) { getArguments().putInt(EXTRA_MODE, MODE_LIST); state.mode = DisplayState.MODE_LIST; updateMode(); getFragmentManager().invalidateOptionsMenu(); return true; } else if (id == R.id.menu_sort) { SortFragment.show(this); return true; } else { return super.onOptionsItemSelected(item); Loading @@ -192,19 +207,19 @@ public class DirectoryFragment extends Fragment { } private void updateMode() { final int mode = getMode(); final DisplayState state = getDisplayState(this); mListView.setVisibility(mode == MODE_LIST ? View.VISIBLE : View.GONE); mGridView.setVisibility(mode == MODE_GRID ? View.VISIBLE : View.GONE); mListView.setVisibility(state.mode == DisplayState.MODE_LIST ? View.VISIBLE : View.GONE); mGridView.setVisibility(state.mode == DisplayState.MODE_GRID ? View.VISIBLE : View.GONE); final int choiceMode; if (getArguments().getBoolean(EXTRA_ALLOW_MULTIPLE)) { if (state.allowMultiple) { choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL; } else { choiceMode = ListView.CHOICE_MODE_NONE; } if (mode == MODE_GRID) { if (state.mode == DisplayState.MODE_GRID) { mListView.setAdapter(null); mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); mGridView.setAdapter(mAdapter); Loading @@ -212,15 +227,21 @@ public class DirectoryFragment extends Fragment { mGridView.setNumColumns(GridView.AUTO_FIT); mGridView.setChoiceMode(choiceMode); mCurrentView = mGridView; } else { } else if (state.mode == DisplayState.MODE_LIST) { mGridView.setAdapter(null); mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE); mListView.setAdapter(mAdapter); mListView.setChoiceMode(choiceMode); mCurrentView = mListView; } else { throw new IllegalStateException(); } } private void updateSortBy() { getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); } private OnItemClickListener mItemListener = new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Loading Loading @@ -288,12 +309,8 @@ public class DirectoryFragment extends Fragment { } }; private boolean getSupportsCreate() { return (mFlags & DocumentsContract.FLAG_SUPPORTS_CREATE) != 0; } private int getMode() { return getArguments().getInt(EXTRA_MODE, MODE_LIST); private static DisplayState getDisplayState(Fragment fragment) { return ((DocumentsActivity) fragment.getActivity()).getDisplayState(); } private class DocumentsAdapter extends CursorAdapter { Loading @@ -304,10 +321,10 @@ public class DirectoryFragment extends Fragment { @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { final LayoutInflater inflater = LayoutInflater.from(context); final int mode = getMode(); if (mode == MODE_LIST) { final DisplayState state = getDisplayState(DirectoryFragment.this); if (state.mode == DisplayState.MODE_LIST) { return inflater.inflate(R.layout.item_doc_list, parent, false); } else if (mode == MODE_GRID) { } else if (state.mode == DisplayState.MODE_GRID) { return inflater.inflate(R.layout.item_doc_grid, parent, false); } else { throw new IllegalStateException(); Loading Loading @@ -341,6 +358,38 @@ public class DirectoryFragment extends Fragment { } } public static class SortFragment extends DialogFragment { public static void show(DirectoryFragment parent) { if (!parent.isAdded()) return; final SortFragment dialog = new SortFragment(); dialog.setTargetFragment(parent, 0); dialog.show(parent.getFragmentManager(), TAG_SORT); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Context context = getActivity(); final DisplayState state = getDisplayState(this); final AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.menu_sort); builder.setSingleChoiceItems(new CharSequence[] { getText(R.string.sort_name), getText(R.string.sort_date), }, state.sortBy, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { state.sortBy = which; ((DirectoryFragment) getTargetFragment()).updateSortBy(); dismiss(); } }); return builder.create(); } } private static int getDocumentFlags(Context context, Uri uri) { final Cursor cursor = context.getContentResolver().query(uri, new String[] { DocumentColumns.FLAGS }, null, null, null); Loading
packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java +62 −18 Original line number Diff line number Diff line Loading @@ -55,13 +55,14 @@ public class DocumentsActivity extends Activity { // TODO: fragment to show recently opened documents // TODO: pull actionbar icon from current backend private static final int MODE_OPEN = 1; private static final int MODE_CREATE = 2; private static final int ACTION_OPEN = 1; private static final int ACTION_CREATE = 2; private int mMode; private boolean mAllowMultiple; private int mAction; private String[] mAcceptMimes; private final DisplayState mDisplayState = new DisplayState(); private boolean mIgnoreNextNavigation; private Uri mCurrentDir; Loading @@ -74,11 +75,11 @@ public class DocumentsActivity extends Activity { final Intent intent = getIntent(); final String action = intent.getAction(); if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) { mMode = MODE_OPEN; mAllowMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); mAction = ACTION_OPEN; mDisplayState.allowMultiple = intent.getBooleanExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) { mMode = MODE_CREATE; mAllowMultiple = false; mAction = ACTION_CREATE; mDisplayState.allowMultiple = false; } if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) { Loading @@ -87,6 +88,12 @@ public class DocumentsActivity extends Activity { mAcceptMimes = new String[] { intent.getType() }; } if (mimeMatches("image/*", mAcceptMimes)) { mDisplayState.mode = DisplayState.MODE_GRID; } else { mDisplayState.mode = DisplayState.MODE_LIST; } setResult(Activity.RESULT_CANCELED); setContentView(R.layout.activity); Loading @@ -95,7 +102,7 @@ public class DocumentsActivity extends Activity { updateActionBar(); if (mMode == MODE_CREATE) { if (mAction == ACTION_CREATE) { final String mimeType = getIntent().getType(); final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE); SaveFragment.show(getFragmentManager(), mimeType, title); Loading @@ -120,9 +127,9 @@ public class DocumentsActivity extends Activity { actionBar.setDisplayShowHomeEnabled(false); actionBar.setDisplayHomeAsUpEnabled(false); if (mMode == MODE_OPEN) { if (mAction == ACTION_OPEN) { actionBar.setTitle(R.string.title_open); } else if (mMode == MODE_CREATE) { } else if (mAction == ACTION_CREATE) { actionBar.setTitle(R.string.title_save); } } Loading @@ -140,7 +147,7 @@ public class DocumentsActivity extends Activity { super.onPrepareOptionsMenu(menu); final MenuItem createDir = menu.findItem(R.id.menu_create_dir); createDir.setVisible(mMode == MODE_CREATE); createDir.setVisible(mAction == ACTION_CREATE); createDir.setEnabled(mCurrentSupportsCreate); return true; Loading Loading @@ -209,11 +216,15 @@ public class DocumentsActivity extends Activity { } }; public DisplayState getDisplayState() { return mDisplayState; } public void onDirectoryChanged(Uri uri, int flags) { mCurrentDir = uri; mCurrentSupportsCreate = (flags & DocumentsContract.FLAG_SUPPORTS_CREATE) != 0; if (mMode == MODE_CREATE) { if (mAction == ACTION_CREATE) { final FragmentManager fm = getFragmentManager(); SaveFragment.get(fm).setSaveEnabled(mCurrentSupportsCreate); } Loading @@ -225,18 +236,18 @@ public class DocumentsActivity extends Activity { final Uri uri = DocumentsContract.buildDocumentUri( info.authority, DocumentsContract.ROOT_GUID); final CharSequence displayName = info.loadLabel(getPackageManager()); DirectoryFragment.show(getFragmentManager(), uri, displayName.toString(), mAllowMultiple); DirectoryFragment.show(getFragmentManager(), uri, displayName.toString()); } public void onDocumentPicked(Document doc) { final FragmentManager fm = getFragmentManager(); if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(doc.mimeType)) { // Nested directory picked, recurse using new fragment DirectoryFragment.show(fm, doc.uri, doc.displayName, mAllowMultiple); } else if (mMode == MODE_OPEN) { DirectoryFragment.show(fm, doc.uri, doc.displayName); } else if (mAction == ACTION_OPEN) { // Explicit file picked, return onFinished(doc.uri); } else if (mMode == MODE_CREATE) { } else if (mAction == ACTION_CREATE) { // Overwrite current filename SaveFragment.get(fm).setDisplayName(doc.displayName); } Loading Loading @@ -274,7 +285,7 @@ public class DocumentsActivity extends Activity { intent.addFlags( Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION); if (mMode == MODE_CREATE) { if (mAction == ACTION_CREATE) { intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } Loading @@ -282,6 +293,18 @@ public class DocumentsActivity extends Activity { finish(); } public static class DisplayState { public int mode; public int sortBy; public boolean allowMultiple; public static final int MODE_LIST = 0; public static final int MODE_GRID = 1; public static final int SORT_BY_NAME = 0; public static final int SORT_BY_DATE = 1; } public static class Document { public Uri uri; public String mimeType; Loading @@ -297,6 +320,27 @@ public class DocumentsActivity extends Activity { } } public static boolean mimeMatches(String filter, String[] tests) { for (String test : tests) { if (mimeMatches(filter, test)) { return true; } } return false; } public static boolean mimeMatches(String filter, String test) { if (filter.equals(test)) { return true; } else if ("*/*".equals(filter)) { return true; } else if (filter.endsWith("/*")) { return filter.regionMatches(0, test, 0, filter.indexOf('/')); } else { return false; } } public static Drawable resolveDocumentIcon(Context context, String mimeType) { // TODO: allow backends to provide custom MIME icons if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { Loading