DirectoryFragment.java revision dc2963aecaf38bf53d6de82957412a486049c207
19e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey/* 29e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project 39e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * 49e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 59e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * you may not use this file except in compliance with the License. 69e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * You may obtain a copy of the License at 79e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * 89e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 99e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * 109e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 119e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 129e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * See the License for the specific language governing permissions and 149e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey * limitations under the License. 159e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey */ 169e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 179e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeypackage com.android.documentsui; 189e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 1954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.app.Fragment; 209e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.FragmentManager; 219e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.FragmentTransaction; 229e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.LoaderManager.LoaderCallbacks; 239e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.content.Context; 249e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.content.CursorLoader; 259e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.content.Loader; 269e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.database.Cursor; 279e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.net.Uri; 289e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.os.Bundle; 299e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.provider.DocumentsContract; 309e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.provider.DocumentsContract.DocumentColumns; 3154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.text.format.DateUtils; 32be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.util.SparseBooleanArray; 33be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.view.ActionMode; 349e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.LayoutInflater; 3554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.Menu; 3654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.MenuInflater; 3754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.MenuItem; 389e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.View; 399e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.ViewGroup; 40be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.widget.AbsListView; 41be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.widget.AbsListView.MultiChoiceModeListener; 4254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.AdapterView; 4354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.AdapterView.OnItemClickListener; 449e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.CursorAdapter; 4554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.GridView; 469e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.ImageView; 479e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.ListView; 489e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.TextView; 499e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 501482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkeyimport com.android.documentsui.DocumentsActivity.DisplayState; 5154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport com.android.documentsui.DocumentsActivity.Document; 52be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport com.google.android.collect.Lists; 53be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 54be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.ArrayList; 5554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 5654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey/** 5754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey * Display the documents inside a single directory. 5854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey */ 5954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeypublic class DirectoryFragment extends Fragment { 6054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 6154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey // TODO: show storage backend in item views when requested 6292d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey // TODO: apply sort order locally 6392d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey // TODO: apply MIME filtering locally 641482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey 6554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey private ListView mListView; 6654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey private GridView mGridView; 6754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 68be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey private AbsListView mCurrentView; 69be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 70dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey private static final int TYPE_NORMAL = 1; 71dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey private static final int TYPE_SEARCH = 2; 72dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey private static final int TYPE_RECENT_OPEN = 3; 73dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey private static final int TYPE_RECENT_CREATE = 4; 74dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey 75dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey private int mType = TYPE_NORMAL; 76dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey 779e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey private DocumentsAdapter mAdapter; 789e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey private LoaderCallbacks<Cursor> mCallbacks; 799e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 80dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey private static final String EXTRA_URI = "uri"; 819e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 829e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey private static final int LOADER_DOCUMENTS = 2; 839e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 84dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey public static void show(FragmentManager fm, Uri uri) { 859e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final Bundle args = new Bundle(); 86dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey args.putParcelable(EXTRA_URI, uri); 879e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 889e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final DirectoryFragment fragment = new DirectoryFragment(); 899e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey fragment.setArguments(args); 909e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 919e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final FragmentTransaction ft = fm.beginTransaction(); 9254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey ft.replace(R.id.directory, fragment); 939e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey ft.commitAllowingStateLoss(); 949e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 959e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 969e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 9754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public void onCreate(Bundle savedInstanceState) { 9854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey super.onCreate(savedInstanceState); 9954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey setHasOptionsMenu(true); 10054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 10154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 10254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey @Override 1039e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public View onCreateView( 1049e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 1059e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final Context context = inflater.getContext(); 1069e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 10754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey final View view = inflater.inflate(R.layout.fragment_directory, container, false); 10854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 10954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mListView = (ListView) view.findViewById(R.id.list); 11054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mListView.setOnItemClickListener(mItemListener); 111be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mListView.setMultiChoiceModeListener(mMultiListener); 11254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 11354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView = (GridView) view.findViewById(R.id.grid); 11454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView.setOnItemClickListener(mItemListener); 115be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mGridView.setMultiChoiceModeListener(mMultiListener); 11654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 1179e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey mAdapter = new DocumentsAdapter(context); 11854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey updateMode(); 11954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 120dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey final Uri uri = getArguments().getParcelable(EXTRA_URI); 121dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey 122dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey if (uri.getQueryParameter(DocumentsContract.PARAM_QUERY) != null) { 123dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey mType = TYPE_SEARCH; 124dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey } else if (RecentsProvider.buildRecentOpen().equals(uri)) { 125dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey mType = TYPE_RECENT_OPEN; 126dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey } else if (RecentsProvider.buildRecentCreate().equals(uri)) { 127dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey mType = TYPE_RECENT_CREATE; 128dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey } else { 129dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey mType = TYPE_NORMAL; 130dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey } 1319e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 1329e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey mCallbacks = new LoaderCallbacks<Cursor>() { 1339e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 1349e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public Loader<Cursor> onCreateLoader(int id, Bundle args) { 1351482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey final DisplayState state = getDisplayState(DirectoryFragment.this); 1361482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey final String sortOrder; 1371482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey if (state.sortBy == DisplayState.SORT_BY_NAME) { 1381482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey sortOrder = DocumentColumns.DISPLAY_NAME + " ASC"; 1391482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey } else if (state.sortBy == DisplayState.SORT_BY_DATE) { 1401482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey sortOrder = DocumentColumns.LAST_MODIFIED + " DESC"; 1411482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey } else { 1421482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey sortOrder = null; 1431482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey } 1441482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey 145bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey final Uri contentsUri; 146dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey if (mType == TYPE_NORMAL) { 147dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey contentsUri = DocumentsContract.buildContentsUri(uri); 148bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey } else { 149dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey contentsUri = uri; 150bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey } 151bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey 1521482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey return new CursorLoader(context, contentsUri, null, null, null, sortOrder); 1539e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 1549e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 1559e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 1569e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 1579e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey mAdapter.swapCursor(data); 1589e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 1599e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 1609e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 1619e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public void onLoaderReset(Loader<Cursor> loader) { 1629e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey mAdapter.swapCursor(null); 1639e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 1649e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey }; 1659e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 16654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey return view; 1679e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 1689e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 1699e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 1709e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public void onStart() { 1719e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey super.onStart(); 1729e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); 1739e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 1749e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 1759e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 1769e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public void onStop() { 1779e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey super.onStop(); 1789e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey getLoaderManager().destroyLoader(LOADER_DOCUMENTS); 1799e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 1809e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 1819e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 18254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 18354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey super.onCreateOptionsMenu(menu, inflater); 18454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey inflater.inflate(R.menu.directory, menu); 18554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 1869e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 18754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey @Override 18854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public void onPrepareOptionsMenu(Menu menu) { 18954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey super.onPrepareOptionsMenu(menu); 1901482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey final DisplayState state = getDisplayState(this); 1911482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey menu.findItem(R.id.menu_grid).setVisible(state.mode != DisplayState.MODE_GRID); 1921482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey menu.findItem(R.id.menu_list).setVisible(state.mode != DisplayState.MODE_LIST); 19354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 19454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 19554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey @Override 19654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public boolean onOptionsItemSelected(MenuItem item) { 1971482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey final DisplayState state = getDisplayState(this); 19854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey final int id = item.getItemId(); 19954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey if (id == R.id.menu_grid) { 2001482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey state.mode = DisplayState.MODE_GRID; 20154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey updateMode(); 2021482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey getFragmentManager().invalidateOptionsMenu(); 20354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey return true; 20454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } else if (id == R.id.menu_list) { 2051482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey state.mode = DisplayState.MODE_LIST; 20654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey updateMode(); 2071482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey getFragmentManager().invalidateOptionsMenu(); 2081482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey return true; 2099e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } else { 21054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey return super.onOptionsItemSelected(item); 2119e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 2129e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 2139e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 21454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey private void updateMode() { 2151482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey final DisplayState state = getDisplayState(this); 21654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 2171482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey mListView.setVisibility(state.mode == DisplayState.MODE_LIST ? View.VISIBLE : View.GONE); 2181482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey mGridView.setVisibility(state.mode == DisplayState.MODE_GRID ? View.VISIBLE : View.GONE); 21954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 220be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey final int choiceMode; 2211482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey if (state.allowMultiple) { 222be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL; 223be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } else { 224be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey choiceMode = ListView.CHOICE_MODE_NONE; 225be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 226be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 2271482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey if (state.mode == DisplayState.MODE_GRID) { 22854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mListView.setAdapter(null); 229be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); 23054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView.setAdapter(mAdapter); 231be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mGridView.setColumnWidth(getResources().getDimensionPixelSize(R.dimen.grid_width)); 23254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView.setNumColumns(GridView.AUTO_FIT); 233be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mGridView.setChoiceMode(choiceMode); 234be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mCurrentView = mGridView; 2351482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey } else if (state.mode == DisplayState.MODE_LIST) { 23654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView.setAdapter(null); 237be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE); 23854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mListView.setAdapter(mAdapter); 239be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mListView.setChoiceMode(choiceMode); 240be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mCurrentView = mListView; 2411482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey } else { 2421482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey throw new IllegalStateException(); 24354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 24454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 24554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 246bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey public void updateSortBy() { 2471482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey getLoaderManager().restartLoader(LOADER_DOCUMENTS, getArguments(), mCallbacks); 2481482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey } 2491482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey 25054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey private OnItemClickListener mItemListener = new OnItemClickListener() { 25154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey @Override 25254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 25354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey final Cursor cursor = (Cursor) mAdapter.getItem(position); 254dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey final Uri uri = getArguments().getParcelable(EXTRA_URI); 255dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey final Document doc = Document.fromCursor(uri, cursor); 25654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey ((DocumentsActivity) getActivity()).onDocumentPicked(doc); 25754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 25854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey }; 25954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 260be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey private MultiChoiceModeListener mMultiListener = new MultiChoiceModeListener() { 261be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 262be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public boolean onCreateActionMode(ActionMode mode, Menu menu) { 263be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mode.getMenuInflater().inflate(R.menu.mode_directory, menu); 264be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey return true; 265be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 266be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 267be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 268be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 269be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey return true; 270be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 271be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 272be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 273be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 274be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey if (item.getItemId() == R.id.menu_open) { 275dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey final Uri uri = getArguments().getParcelable(EXTRA_URI); 276be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions(); 277be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey final ArrayList<Document> docs = Lists.newArrayList(); 278be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 279be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey final int size = checked.size(); 280be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey for (int i = 0; i < size; i++) { 281be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey if (checked.valueAt(i)) { 282be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey final Cursor cursor = (Cursor) mAdapter.getItem(checked.keyAt(i)); 283dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey docs.add(Document.fromCursor(uri, cursor)); 284be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 285be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 286be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 287be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey ((DocumentsActivity) getActivity()).onDocumentsPicked(docs); 288be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey return true; 289be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } else { 290be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey return false; 291be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 292be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 293be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 294be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 295be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public void onDestroyActionMode(ActionMode mode) { 296be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey // ignored 297be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 298be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 299be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 300be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public void onItemCheckedStateChanged( 301be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey ActionMode mode, int position, long id, boolean checked) { 302be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey if (checked) { 303be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey final Cursor cursor = (Cursor) mAdapter.getItem(position); 304be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); 305be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 306be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey // Directories cannot be checked 307be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) { 308be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mCurrentView.setItemChecked(position, false); 309be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 310be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 311be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 312be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mode.setTitle(getResources() 313be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey .getString(R.string.mode_selected_count, mCurrentView.getCheckedItemCount())); 314be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 315be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey }; 316be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 3171482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey private static DisplayState getDisplayState(Fragment fragment) { 3181482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey return ((DocumentsActivity) fragment.getActivity()).getDisplayState(); 31954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 32054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 3219e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey private class DocumentsAdapter extends CursorAdapter { 3229e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public DocumentsAdapter(Context context) { 3239e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey super(context, null, false); 3249e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 3259e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 3269e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 3279e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public View newView(Context context, Cursor cursor, ViewGroup parent) { 32854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey final LayoutInflater inflater = LayoutInflater.from(context); 3291482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey final DisplayState state = getDisplayState(DirectoryFragment.this); 3301482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey if (state.mode == DisplayState.MODE_LIST) { 33154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey return inflater.inflate(R.layout.item_doc_list, parent, false); 3321482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey } else if (state.mode == DisplayState.MODE_GRID) { 33354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey return inflater.inflate(R.layout.item_doc_grid, parent, false); 33454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } else { 33554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey throw new IllegalStateException(); 33654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 3379e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 3389e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 3399e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 3409e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public void bindView(View view, Context context, Cursor cursor) { 3419e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final TextView title = (TextView) view.findViewById(android.R.id.title); 3429e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final TextView summary = (TextView) view.findViewById(android.R.id.summary); 3439e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final ImageView icon = (ImageView) view.findViewById(android.R.id.icon); 3449e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 34592d7e697a864a3e18bef4ef256bb3eb339a66b4eJeff Sharkey final String docId = getCursorString(cursor, DocumentColumns.DOC_ID); 3469e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME); 3479e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE); 34854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey final long lastModified = getCursorLong(cursor, DocumentColumns.LAST_MODIFIED); 3499e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final int flags = getCursorInt(cursor, DocumentColumns.FLAGS); 3509e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 351dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey final Uri uri = getArguments().getParcelable(EXTRA_URI); 3529e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey if ((flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0) { 353dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey final Uri childUri = DocumentsContract.buildDocumentUri(uri, docId); 3549e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey icon.setImageURI(childUri); 3559e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } else { 356dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey icon.setImageDrawable(DocumentsActivity.resolveDocumentIcon( 357dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey context, uri.getAuthority(), mimeType)); 3589e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 3599e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 3609e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey title.setText(displayName); 36154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey if (summary != null) { 36254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey summary.setText(DateUtils.getRelativeTimeSpanString(lastModified)); 36354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 36454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 36554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 36654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 36754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public static String getCursorString(Cursor cursor, String columnName) { 3689e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey return cursor.getString(cursor.getColumnIndex(columnName)); 3699e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 3709e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 37154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public static long getCursorLong(Cursor cursor, String columnName) { 37254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey return cursor.getLong(cursor.getColumnIndex(columnName)); 37354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 37454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 37554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public static int getCursorInt(Cursor cursor, String columnName) { 3769e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey return cursor.getInt(cursor.getColumnIndex(columnName)); 3779e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 3789e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey} 379