DirectoryFragment.java revision e20a3acdc2d52c7eeb76940206145b3c419394a6
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 199d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkeyimport static com.android.documentsui.DocumentsActivity.TAG; 20b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.ACTION_MANAGE; 21b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.MODE_GRID; 22b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.MODE_LIST; 23d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.MODE_UNKNOWN; 24d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_UNKNOWN; 255dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport static com.android.documentsui.model.DocumentInfo.getCursorInt; 265dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport static com.android.documentsui.model.DocumentInfo.getCursorLong; 275dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport static com.android.documentsui.model.DocumentInfo.getCursorString; 289d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 2954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.app.Fragment; 309e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.FragmentManager; 319e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.FragmentTransaction; 329e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.app.LoaderManager.LoaderCallbacks; 334eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.content.ContentResolver; 34fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkeyimport android.content.ContentValues; 359e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.content.Context; 364eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.content.Intent; 379e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.content.Loader; 385dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.database.Cursor; 399d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkeyimport android.graphics.Bitmap; 409d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkeyimport android.graphics.Point; 414ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.graphics.drawable.Drawable; 429e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.net.Uri; 439d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkeyimport android.os.AsyncTask; 449e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.os.Bundle; 454ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.os.CancellationSignal; 46e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport android.os.Parcelable; 479e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.provider.DocumentsContract; 485dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkeyimport android.provider.DocumentsContract.Document; 4954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.text.format.DateUtils; 50b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.text.format.Formatter; 519d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkeyimport android.text.format.Time; 529d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkeyimport android.util.Log; 53e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkeyimport android.util.SparseArray; 54be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.util.SparseBooleanArray; 55be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.view.ActionMode; 569e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.LayoutInflater; 5754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.Menu; 5854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.MenuItem; 599e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.View; 609e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.ViewGroup; 61be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.widget.AbsListView; 62be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.widget.AbsListView.MultiChoiceModeListener; 634ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkeyimport android.widget.AbsListView.RecyclerListener; 6454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.AdapterView; 6554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.AdapterView.OnItemClickListener; 66ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.widget.BaseAdapter; 6754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.GridView; 689e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.ImageView; 699e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.ListView; 709e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.TextView; 714eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkeyimport android.widget.Toast; 729e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 73b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport com.android.documentsui.DocumentsActivity.State; 74fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkeyimport com.android.documentsui.RecentsProvider.StateColumns; 75ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo; 76251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkeyimport com.android.documentsui.model.RootInfo; 77ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport com.android.internal.util.Predicate; 78be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport com.google.android.collect.Lists; 79be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 80be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.ArrayList; 81ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport java.util.List; 82b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport java.util.concurrent.atomic.AtomicInteger; 8354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 8454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey/** 8554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey * Display the documents inside a single directory. 8654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey */ 8754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeypublic class DirectoryFragment extends Fragment { 8854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 899fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey private View mEmptyView; 9054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey private ListView mListView; 9154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey private GridView mGridView; 9254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 93be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey private AbsListView mCurrentView; 94be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 95ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private Predicate<DocumentInfo> mFilter; 969fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey 97ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey public static final int TYPE_NORMAL = 1; 98ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey public static final int TYPE_SEARCH = 2; 99251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey public static final int TYPE_RECENT_OPEN = 3; 100dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey 101e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey public static final int ANIM_NONE = 1; 102e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey public static final int ANIM_SIDE = 2; 103e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey public static final int ANIM_DOWN = 3; 104e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey public static final int ANIM_UP = 4; 105e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey 106dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey private int mType = TYPE_NORMAL; 107e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey private String mStateKey; 108dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey 109d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey private int mLastMode = MODE_UNKNOWN; 110d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey private int mLastSortOrder = SORT_ORDER_UNKNOWN; 111ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey private boolean mLastShowSize = false; 112d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 113f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey private boolean mHideGridTitles = false; 114f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 1159d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey private Point mThumbSize; 1169d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 1179e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey private DocumentsAdapter mAdapter; 118b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey private LoaderCallbacks<DirectoryResult> mCallbacks; 1199e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 120b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey private static final String EXTRA_TYPE = "type"; 121d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey private static final String EXTRA_ROOT = "root"; 122d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey private static final String EXTRA_DOC = "doc"; 123251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey private static final String EXTRA_QUERY = "query"; 124e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey private static final String EXTRA_IGNORE_STATE = "ignoreState"; 1259e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 126b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey private static AtomicInteger sLoaderId = new AtomicInteger(4000); 127b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 128b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey private final int mLoaderId = sLoaderId.incrementAndGet(); 129b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 130e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) { 131e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey show(fm, TYPE_NORMAL, root, doc, null, anim); 132b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 133b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 134e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey public static void showSearch(FragmentManager fm, RootInfo root, String query, int anim) { 135e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey show(fm, TYPE_SEARCH, root, null, query, anim); 136b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 137b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 138e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey public static void showRecentsOpen(FragmentManager fm, int anim) { 139e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey show(fm, TYPE_RECENT_OPEN, null, null, null, anim); 140b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 1419e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 142e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey private static void show(FragmentManager fm, int type, RootInfo root, DocumentInfo doc, 143e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey String query, int anim) { 1449e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final Bundle args = new Bundle(); 145b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey args.putInt(EXTRA_TYPE, type); 146d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey args.putParcelable(EXTRA_ROOT, root); 147d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey args.putParcelable(EXTRA_DOC, doc); 148251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey args.putString(EXTRA_QUERY, query); 1499e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 150e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey final FragmentTransaction ft = fm.beginTransaction(); 151e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey switch (anim) { 152e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey case ANIM_SIDE: 153e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey args.putBoolean(EXTRA_IGNORE_STATE, true); 154e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey break; 155e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey case ANIM_DOWN: 156e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey args.putBoolean(EXTRA_IGNORE_STATE, true); 157e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey ft.setCustomAnimations(R.animator.dir_down, R.animator.dir_frozen); 158e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey break; 159e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey case ANIM_UP: 160e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey ft.setCustomAnimations(R.animator.dir_frozen, R.animator.dir_up); 161e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey break; 162e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey } 163e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey 1649e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final DirectoryFragment fragment = new DirectoryFragment(); 1659e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey fragment.setArguments(args); 1669e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 16766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey ft.replace(R.id.container_directory, fragment); 1689e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey ft.commitAllowingStateLoss(); 1699e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 1709e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 171e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey private static String buildStateKey(RootInfo root, DocumentInfo doc) { 172e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey final StringBuilder builder = new StringBuilder(); 173e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey builder.append(root != null ? root.authority : "null").append(';'); 174e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey builder.append(root != null ? root.rootId : "null").append(';'); 175e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey builder.append(doc != null ? doc.documentId : "null"); 176e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey return builder.toString(); 177e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey } 178e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey 179ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey public static DirectoryFragment get(FragmentManager fm) { 180ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey // TODO: deal with multiple directories shown at once 18166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey return (DirectoryFragment) fm.findFragmentById(R.id.container_directory); 182ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 183ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 1849e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 1859e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey public View onCreateView( 1869e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 1879e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey final Context context = inflater.getContext(); 18854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey final View view = inflater.inflate(R.layout.fragment_directory, container, false); 18954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 1909fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey mEmptyView = view.findViewById(android.R.id.empty); 1919fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey 19254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mListView = (ListView) view.findViewById(R.id.list); 19354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mListView.setOnItemClickListener(mItemListener); 194be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mListView.setMultiChoiceModeListener(mMultiListener); 1954ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mListView.setRecyclerListener(mRecycleListener); 19654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 19754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView = (GridView) view.findViewById(R.id.grid); 19854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView.setOnItemClickListener(mItemListener); 199be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mGridView.setMultiChoiceModeListener(mMultiListener); 2004ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mGridView.setRecyclerListener(mRecycleListener); 20154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 2025dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey return view; 2035dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 20454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 2055dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey @Override 2065dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey public void onActivityCreated(Bundle savedInstanceState) { 2075dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey super.onActivityCreated(savedInstanceState); 2085dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 2095dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final Context context = getActivity(); 210d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey final State state = getDisplayState(DirectoryFragment.this); 2115dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 212f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey final RootInfo root = getArguments().getParcelable(EXTRA_ROOT); 213f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); 214f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 215251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey mAdapter = new DocumentsAdapter(); 216b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey mType = getArguments().getInt(EXTRA_TYPE); 217e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey mStateKey = buildStateKey(root, doc); 2189e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 219f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (mType == TYPE_RECENT_OPEN) { 220f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey // Hide titles when showing recents for picking images/videos 221f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey mHideGridTitles = MimePredicate.mimeMatches( 222f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey MimePredicate.VISUAL_MIMES, state.acceptMimes); 223f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey } else { 224f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey mHideGridTitles = (doc != null) && doc.isGridTitlesHidden(); 225f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey } 226f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 227b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey mCallbacks = new LoaderCallbacks<DirectoryResult>() { 2289e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 229b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) { 230251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final String query = getArguments().getString(EXTRA_QUERY); 231251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey 23254ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey Uri contentsUri; 233251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey switch (mType) { 234251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey case TYPE_NORMAL: 235d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey contentsUri = DocumentsContract.buildChildDocumentsUri( 236d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey doc.authority, doc.documentId); 2374ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey if (state.action == ACTION_MANAGE) { 2384ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey contentsUri = DocumentsContract.setManageMode(contentsUri); 2394ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 240fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey return new DirectoryLoader( 2414ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey context, mType, root, doc, contentsUri, state.userSortOrder); 242251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey case TYPE_SEARCH: 243251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey contentsUri = DocumentsContract.buildSearchDocumentsUri( 2443e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey root.authority, root.rootId, query); 2454ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey if (state.action == ACTION_MANAGE) { 2464ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey contentsUri = DocumentsContract.setManageMode(contentsUri); 2474ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 248fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey return new DirectoryLoader( 2494ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey context, mType, root, doc, contentsUri, state.userSortOrder); 250251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey case TYPE_RECENT_OPEN: 251348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey final RootsCache roots = DocumentsApplication.getRootsCache(context); 252348ad6866b91afa4d59d45df533ef88094c74d13Jeff Sharkey final List<RootInfo> matchingRoots = roots.getMatchingRoots(state); 253d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey return new RecentLoader(context, matchingRoots, state.acceptMimes); 254251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey default: 255251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey throw new IllegalStateException("Unknown type " + mType); 256251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey } 2579e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 2589e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 2599e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 260b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) { 261d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey if (!isAdded()) return; 262d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 2635dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mAdapter.swapCursor(result.cursor); 264d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 265d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey // Push latest state up to UI 266d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey // TODO: if mode change was racing with us, don't overwrite it 26788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey if (result.mode != MODE_UNKNOWN) { 26888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey state.derivedMode = result.mode; 26988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } 270fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey state.derivedSortOrder = result.sortOrder; 271d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey ((DocumentsActivity) context).onStateChanged(); 272d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 273d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey updateDisplayState(); 274d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 275e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey // Restore any previous instance state 276e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey final SparseArray<Parcelable> container = state.dirState.remove(mStateKey); 277e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey if (container != null && !getArguments().getBoolean(EXTRA_IGNORE_STATE, false)) { 278e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey getView().restoreHierarchyState(container); 279e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey } else if (mLastSortOrder != state.derivedSortOrder) { 280d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey mListView.smoothScrollToPosition(0); 281d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey mGridView.smoothScrollToPosition(0); 282d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey } 283e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey 284e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey mLastSortOrder = state.derivedSortOrder; 2859e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 2869e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 2879e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 288b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey public void onLoaderReset(Loader<DirectoryResult> loader) { 2895dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mAdapter.swapCursor(null); 2909e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 2919e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey }; 2929e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 293d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey // Kick off loader at least once 294d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey getLoaderManager().restartLoader(mLoaderId, null, mCallbacks); 295d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 296b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey updateDisplayState(); 29754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 2989e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 29928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey @Override 300e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey public void onStop() { 301e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey super.onStop(); 302e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey 303e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey // Remember last scroll location 304e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey final SparseArray<Parcelable> container = new SparseArray<Parcelable>(); 305e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey getView().saveHierarchyState(container); 306e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey final State state = getDisplayState(this); 307e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey state.dirState.put(mStateKey, container); 308e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey } 309e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey 310e20a3acdc2d52c7eeb76940206145b3c419394a6Jeff Sharkey @Override 31188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey public void onResume() { 31288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey super.onResume(); 31328c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey updateDisplayState(); 31428c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey } 31528c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey 316d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey public void onUserSortOrderChanged() { 317fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey // Sort order change always triggers reload; we'll trigger state change 318fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey // on the flip side. 319d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey getLoaderManager().restartLoader(mLoaderId, null, mCallbacks); 320d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey } 321d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 322d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey public void onUserModeChanged() { 323fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey final ContentResolver resolver = getActivity().getContentResolver(); 324fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey final State state = getDisplayState(this); 325fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey 326fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey final RootInfo root = getArguments().getParcelable(EXTRA_ROOT); 327fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); 328fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey 3293e1189b3590aefb65a2af720ae2ba959bbd4188dJeff Sharkey if (root != null && doc != null) { 33088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey final Uri stateUri = RecentsProvider.buildState( 33188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey root.authority, root.rootId, doc.documentId); 33288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey final ContentValues values = new ContentValues(); 33388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey values.put(StateColumns.MODE, state.userMode); 33488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey 33588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey new AsyncTask<Void, Void, Void>() { 33688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey @Override 33788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey protected Void doInBackground(Void... params) { 33888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey resolver.insert(stateUri, values); 33988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey return null; 34088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } 34188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey }.execute(); 34288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } 343fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey 344fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey // Mode change is just visual change; no need to kick loader, and 345fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey // deliver change event immediately. 346fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey state.derivedMode = state.userMode; 347fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey ((DocumentsActivity) getActivity()).onStateChanged(); 348fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey 349d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey updateDisplayState(); 350d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey } 351d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey 352d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey private void updateDisplayState() { 353b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey final State state = getDisplayState(this); 35454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 355d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey mFilter = new MimePredicate(state.acceptMimes); 3565dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 357ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey if (mLastMode == state.derivedMode && mLastShowSize == state.showSize) return; 358fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey mLastMode = state.derivedMode; 359ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey mLastShowSize = state.showSize; 36054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 361fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey mListView.setVisibility(state.derivedMode == MODE_LIST ? View.VISIBLE : View.GONE); 362fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey mGridView.setVisibility(state.derivedMode == MODE_GRID ? View.VISIBLE : View.GONE); 36354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 364be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey final int choiceMode; 3651482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey if (state.allowMultiple) { 366be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL; 367be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } else { 368be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey choiceMode = ListView.CHOICE_MODE_NONE; 369be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 370be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 3719d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey final int thumbSize; 372fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey if (state.derivedMode == MODE_GRID) { 3739d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width); 37454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mListView.setAdapter(null); 375be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mListView.setChoiceMode(ListView.CHOICE_MODE_NONE); 37654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView.setAdapter(mAdapter); 377be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mGridView.setColumnWidth(getResources().getDimensionPixelSize(R.dimen.grid_width)); 37854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView.setNumColumns(GridView.AUTO_FIT); 379be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mGridView.setChoiceMode(choiceMode); 380be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mCurrentView = mGridView; 381fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey } else if (state.derivedMode == MODE_LIST) { 382d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size); 38354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mGridView.setAdapter(null); 384be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE); 38554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey mListView.setAdapter(mAdapter); 386be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mListView.setChoiceMode(choiceMode); 387be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mCurrentView = mListView; 3881482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey } else { 389fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey throw new IllegalStateException("Unknown state " + state.derivedMode); 39054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 3919d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 3929d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey mThumbSize = new Point(thumbSize, thumbSize); 39354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 39454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 39554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey private OnItemClickListener mItemListener = new OnItemClickListener() { 39654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey @Override 39754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 3985dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final Cursor cursor = mAdapter.getItem(position); 3993f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey if (cursor != null) { 4003f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor); 4013f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey if (mFilter.apply(doc)) { 4023f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey ((DocumentsActivity) getActivity()).onDocumentPicked(doc); 4033f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 404a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey } 40554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 40654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey }; 40754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 408be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey private MultiChoiceModeListener mMultiListener = new MultiChoiceModeListener() { 409be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 410be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public boolean onCreateActionMode(ActionMode mode, Menu menu) { 411be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mode.getMenuInflater().inflate(R.menu.mode_directory, menu); 412be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey return true; 413be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 414be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 415be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 416be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 417b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey final State state = getDisplayState(DirectoryFragment.this); 4184eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 4194eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final MenuItem open = menu.findItem(R.id.menu_open); 4204eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final MenuItem share = menu.findItem(R.id.menu_share); 4214eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final MenuItem delete = menu.findItem(R.id.menu_delete); 4224eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 4234eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final boolean manageMode = state.action == ACTION_MANAGE; 4244eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey open.setVisible(!manageMode); 4254eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey share.setVisible(manageMode); 4264eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey delete.setVisible(manageMode); 4274eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 428be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey return true; 429be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 430be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 431be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 432be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 4334eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions(); 434ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey final ArrayList<DocumentInfo> docs = Lists.newArrayList(); 4354eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final int size = checked.size(); 4364eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey for (int i = 0; i < size; i++) { 4374eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey if (checked.valueAt(i)) { 4385dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final Cursor cursor = mAdapter.getItem(checked.keyAt(i)); 439251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor); 4404eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey docs.add(doc); 441be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 4424eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } 4434eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 4444eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final int id = item.getItemId(); 4454eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey if (id == R.id.menu_open) { 4464eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey DocumentsActivity.get(DirectoryFragment.this).onDocumentsPicked(docs); 447b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey mode.finish(); 4484eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey return true; 449be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 4504eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } else if (id == R.id.menu_share) { 4514eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey onShareDocuments(docs); 452b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey mode.finish(); 453be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey return true; 4544eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 4554eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } else if (id == R.id.menu_delete) { 4564eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey onDeleteDocuments(docs); 457b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey mode.finish(); 4584eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey return true; 4594eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 460be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } else { 461be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey return false; 462be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 463be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 464be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 465be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 466be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public void onDestroyActionMode(ActionMode mode) { 467be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey // ignored 468be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 469be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 470be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey @Override 471be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey public void onItemCheckedStateChanged( 472be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey ActionMode mode, int position, long id, boolean checked) { 473be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey if (checked) { 4743f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey // Directories and footer items cannot be checked 4753f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey boolean valid = false; 4763f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 4775dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final Cursor cursor = mAdapter.getItem(position); 4783f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey if (cursor != null) { 4793f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); 4803f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 4813f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey // Only valid if non-directory matches filter 4823f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey final State state = getDisplayState(DirectoryFragment.this); 4833f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey valid = !Document.MIME_TYPE_DIR.equals(docMimeType) 4843f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey && MimePredicate.mimeMatches(state.acceptMimes, docMimeType); 4853f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 4863f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 4873f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey if (!valid) { 488be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mCurrentView.setItemChecked(position, false); 489be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 490be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 491be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 492be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey mode.setTitle(getResources() 493be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey .getString(R.string.mode_selected_count, mCurrentView.getCheckedItemCount())); 494be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey } 495be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey }; 496be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey 4974ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey private RecyclerListener mRecycleListener = new RecyclerListener() { 4984ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey @Override 4994ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey public void onMovedToScrapHeap(View view) { 5004ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey final ImageView iconThumb = (ImageView) view.findViewById(R.id.icon_thumb); 5014ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey if (iconThumb != null) { 5024ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag(); 5034ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey if (oldTask != null) { 5044ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey oldTask.reallyCancel(); 5054ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconThumb.setTag(null); 5064ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 5074ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 5084ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 5094ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey }; 5104ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey 511ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private void onShareDocuments(List<DocumentInfo> docs) { 512b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey Intent intent; 513b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey if (docs.size() == 1) { 514b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey final DocumentInfo doc = docs.get(0); 515b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 516b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey intent = new Intent(Intent.ACTION_SEND); 517b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 518b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey intent.addCategory(Intent.CATEGORY_DEFAULT); 519b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey intent.setType(doc.mimeType); 520d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey intent.putExtra(Intent.EXTRA_STREAM, doc.derivedUri); 5214eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 522b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey } else if (docs.size() > 1) { 5234eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey intent = new Intent(Intent.ACTION_SEND_MULTIPLE); 5244eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 5254eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey intent.addCategory(Intent.CATEGORY_DEFAULT); 526b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 527b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey final ArrayList<String> mimeTypes = Lists.newArrayList(); 528b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey final ArrayList<Uri> uris = Lists.newArrayList(); 529b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey for (DocumentInfo doc : docs) { 530b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey mimeTypes.add(doc.mimeType); 531d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey uris.add(doc.derivedUri); 532b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey } 533b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 534b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey intent.setType(findCommonMimeType(mimeTypes)); 5354eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); 536b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 5374eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } else { 538b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey return; 5394eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } 5404eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 541b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey intent = Intent.createChooser(intent, getActivity().getText(R.string.share_via)); 5424eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey startActivity(intent); 5434eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } 5444eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 545ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey private void onDeleteDocuments(List<DocumentInfo> docs) { 5464eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final Context context = getActivity(); 5474eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final ContentResolver resolver = context.getContentResolver(); 5484eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 5494eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey boolean hadTrouble = false; 550ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey for (DocumentInfo doc : docs) { 5514eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey if (!doc.isDeleteSupported()) { 5524eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey Log.w(TAG, "Skipping " + doc); 5534eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey hadTrouble = true; 5544eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey continue; 5554eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } 5564eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 557d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey if (!DocumentsContract.deleteDocument(resolver, doc.derivedUri)) { 558ded77187ef53341765fcab8e29cda94810fc2ca5Jeff Sharkey Log.w(TAG, "Failed to delete " + doc); 5594eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey hadTrouble = true; 5604eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } 5614eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } 5624eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 5634eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey if (hadTrouble) { 5644eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey Toast.makeText(context, R.string.toast_failed_delete, Toast.LENGTH_SHORT).show(); 5654eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } 5664eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey } 5674eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 568b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey private static State getDisplayState(Fragment fragment) { 5691482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey return ((DocumentsActivity) fragment.getActivity()).getDisplayState(); 57054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 57154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 5723f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey private static abstract class Footer { 5733f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey private final int mItemViewType; 5743f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 5753f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey public Footer(int itemViewType) { 5763f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey mItemViewType = itemViewType; 5773f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 5783f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 5793f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey public abstract View getView(View convertView, ViewGroup parent); 5803f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 5813f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey public int getItemViewType() { 5823f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey return mItemViewType; 5833f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 584954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 585954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 586ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey private class LoadingFooter extends Footer { 5873f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey public LoadingFooter() { 5883f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey super(1); 5893f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 5903f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 591954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey @Override 592954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey public View getView(View convertView, ViewGroup parent) { 593954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final Context context = parent.getContext(); 594ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey final State state = getDisplayState(DirectoryFragment.this); 595ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey 596954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (convertView == null) { 597954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final LayoutInflater inflater = LayoutInflater.from(context); 598ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey if (state.derivedMode == MODE_LIST) { 599ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey convertView = inflater.inflate(R.layout.item_loading_list, parent, false); 600ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey } else if (state.derivedMode == MODE_GRID) { 601ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey convertView = inflater.inflate(R.layout.item_loading_grid, parent, false); 602ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey } else { 603ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey throw new IllegalStateException(); 604ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey } 605954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 606ed903213e6d3d75d497498c9cf95aa8e74277a9eJeff Sharkey 607954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey return convertView; 608954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 609954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 610954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 6113f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey private class MessageFooter extends Footer { 612954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey private final int mIcon; 613954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey private final String mMessage; 614954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 6153f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey public MessageFooter(int itemViewType, int icon, String message) { 6163f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey super(itemViewType); 617954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey mIcon = icon; 618954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey mMessage = message; 619954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 620954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 621954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey @Override 622954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey public View getView(View convertView, ViewGroup parent) { 623954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final Context context = parent.getContext(); 624954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final State state = getDisplayState(DirectoryFragment.this); 625954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 626954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (convertView == null) { 627954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final LayoutInflater inflater = LayoutInflater.from(context); 628fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey if (state.derivedMode == MODE_LIST) { 629954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey convertView = inflater.inflate(R.layout.item_message_list, parent, false); 630fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey } else if (state.derivedMode == MODE_GRID) { 631954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey convertView = inflater.inflate(R.layout.item_message_grid, parent, false); 632954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } else { 633954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey throw new IllegalStateException(); 634954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 635954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 636954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 637954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon); 638954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final TextView title = (TextView) convertView.findViewById(android.R.id.title); 639954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey icon.setImageResource(mIcon); 640954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey title.setText(mMessage); 641954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey return convertView; 642954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 643954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 644954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 645ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey private class DocumentsAdapter extends BaseAdapter { 6465dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey private Cursor mCursor; 647954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey private int mCursorCount; 648954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 649954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey private List<Footer> mFooters = Lists.newArrayList(); 650ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 6515dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey public void swapCursor(Cursor cursor) { 6525dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mCursor = cursor; 653954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey mCursorCount = cursor != null ? cursor.getCount() : 0; 654954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 655954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey mFooters.clear(); 656954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 657954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final Bundle extras = cursor != null ? cursor.getExtras() : null; 658954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (extras != null) { 659954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final String info = extras.getString(DocumentsContract.EXTRA_INFO); 660954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (info != null) { 6613f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey mFooters.add(new MessageFooter(2, R.drawable.ic_dialog_alert, info)); 662954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 663954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey final String error = extras.getString(DocumentsContract.EXTRA_ERROR); 664954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (error != null) { 6653f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey mFooters.add(new MessageFooter(3, R.drawable.ic_dialog_alert, error)); 666954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 667954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (extras.getBoolean(DocumentsContract.EXTRA_LOADING, false)) { 668954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey mFooters.add(new LoadingFooter()); 669954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 670954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 6719fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey 6725dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (isEmpty()) { 6739fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey mEmptyView.setVisibility(View.VISIBLE); 6749fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey } else { 6759fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey mEmptyView.setVisibility(View.GONE); 6769fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey } 6779fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey 678ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey notifyDataSetChanged(); 6799e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 6809e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 6819e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey @Override 682ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey public View getView(int position, View convertView, ViewGroup parent) { 683954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (position < mCursorCount) { 684954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey return getDocumentView(position, convertView, parent); 685954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } else { 686954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey position -= mCursorCount; 6873f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey convertView = mFooters.get(position).getView(convertView, parent); 6883f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey // Only the view itself is disabled; contents inside shouldn't 6893f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey // be dimmed. 6903f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey convertView.setEnabled(false); 6913f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey return convertView; 692954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 693954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 694954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 695954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey private View getDocumentView(int position, View convertView, ViewGroup parent) { 696ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey final Context context = parent.getContext(); 697b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey final State state = getDisplayState(DirectoryFragment.this); 698ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 699f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC); 700f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 7014eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final RootsCache roots = DocumentsApplication.getRootsCache(context); 7024eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache( 7034eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey context, mThumbSize); 7044eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey 705ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey if (convertView == null) { 706ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey final LayoutInflater inflater = LayoutInflater.from(context); 707fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey if (state.derivedMode == MODE_LIST) { 708ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey convertView = inflater.inflate(R.layout.item_doc_list, parent, false); 709fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey } else if (state.derivedMode == MODE_GRID) { 710ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey convertView = inflater.inflate(R.layout.item_doc_grid, parent, false); 711ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } else { 712ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey throw new IllegalStateException(); 713ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 714ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 715ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 7165dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final Cursor cursor = getItem(position); 7175dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey 718251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final String docAuthority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY); 719251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final String docRootId = getCursorString(cursor, RootCursorWrapper.COLUMN_ROOT_ID); 7205dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID); 7215dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); 7225dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final String docDisplayName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME); 7235dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final long docLastModified = getCursorLong(cursor, Document.COLUMN_LAST_MODIFIED); 7245dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final int docIcon = getCursorInt(cursor, Document.COLUMN_ICON); 7255dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); 7265dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY); 7275dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE); 728ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 729f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey final View line1 = convertView.findViewById(R.id.line1); 730f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey final View line2 = convertView.findViewById(R.id.line2); 731f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 7324ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey final View icon = convertView.findViewById(android.R.id.icon); 7334ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime); 7344ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey final ImageView iconThumb = (ImageView) convertView.findViewById(R.id.icon_thumb); 735ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey final TextView title = (TextView) convertView.findViewById(android.R.id.title); 736b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1); 737f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey final ImageView icon2 = (ImageView) convertView.findViewById(android.R.id.icon2); 738ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey final TextView summary = (TextView) convertView.findViewById(android.R.id.summary); 739b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final TextView date = (TextView) convertView.findViewById(R.id.date); 740b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final TextView size = (TextView) convertView.findViewById(R.id.size); 741ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 7424ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag(); 7439d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey if (oldTask != null) { 7444ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey oldTask.reallyCancel(); 7454ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconThumb.setTag(null); 7469d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 7479d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 7484ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconMime.animate().cancel(); 7494ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconThumb.animate().cancel(); 7504ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey 7513f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0; 752fb3445c9b31c7f8401d6eec0606dabee366c8aadJeff Sharkey final boolean allowThumbnail = (state.derivedMode == MODE_GRID) 753f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey || MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, docMimeType); 754f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey final boolean showThumbnail = supportsThumbnail && allowThumbnail; 7553f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 7564ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey boolean cacheHit = false; 757f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (showThumbnail) { 758251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId); 7595dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey final Bitmap cachedResult = thumbs.get(uri); 7609d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey if (cachedResult != null) { 7614ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconThumb.setImageBitmap(cachedResult); 7624ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey cacheHit = true; 7639d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } else { 7644ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconThumb.setImageDrawable(null); 7654ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey final ThumbnailAsyncTask task = new ThumbnailAsyncTask( 7664ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey uri, iconMime, iconThumb, mThumbSize); 7674ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconThumb.setTag(task); 7684ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 7699d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 7704ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 7714ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey 7724ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey // Always throw MIME icon into place, even when a thumbnail is being 7734ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey // loaded in background. 7744ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey if (cacheHit) { 7754ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconMime.setAlpha(0f); 7764ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconThumb.setAlpha(1f); 7779e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } else { 7784ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconMime.setAlpha(1f); 7794ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconThumb.setAlpha(0f); 7804ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey if (docIcon != 0) { 7814ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconMime.setImageDrawable( 7824ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey IconUtils.loadPackageIcon(context, docAuthority, docIcon)); 7834ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } else { 7844ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconMime.setImageDrawable(IconUtils.loadMimeIcon(context, docMimeType)); 7854ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 7869e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 7879e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 788f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey boolean hasLine1 = false; 78928c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey boolean hasLine2 = false; 79028c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey 791f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey final boolean hideTitle = (state.derivedMode == MODE_GRID) && mHideGridTitles; 792f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (!hideTitle) { 793f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey title.setText(docDisplayName); 794f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey hasLine1 = true; 795f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey } 796f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 797f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey Drawable iconDrawable = null; 798251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey if (mType == TYPE_RECENT_OPEN) { 799251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey final RootInfo root = roots.getRoot(docAuthority, docRootId); 800f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey iconDrawable = root.loadIcon(context); 8014ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey 80288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey if (summary != null) { 80388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey final boolean alwaysShowSummary = getResources() 80488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey .getBoolean(R.bool.always_show_summary); 80588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey if (alwaysShowSummary) { 80688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setText(root.getDirectoryString()); 80788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setVisibility(View.VISIBLE); 80888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey hasLine2 = true; 80988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } else { 81088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey if (iconDrawable != null && roots.isIconUnique(root)) { 81188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey // No summary needed if icon speaks for itself 81288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setVisibility(View.INVISIBLE); 81388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } else { 81488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setText(root.getDirectoryString()); 81588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setVisibility(View.VISIBLE); 81688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setTextAlignment(TextView.TEXT_ALIGNMENT_TEXT_END); 81788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey hasLine2 = true; 81888f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } 81988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } 8204ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey } 8215dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } else { 822f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey // Directories showing thumbnails in grid mode get a little icon 823f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey // hint to remind user they're a directory. 824f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (Document.MIME_TYPE_DIR.equals(docMimeType) && state.derivedMode == MODE_GRID 825f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey && showThumbnail) { 826f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey iconDrawable = context.getResources().getDrawable(R.drawable.ic_root_folder); 827f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey } 828f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 82988f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey if (summary != null) { 83088f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey if (docSummary != null) { 83188f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setText(docSummary); 83288f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setVisibility(View.VISIBLE); 83388f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey hasLine2 = true; 83488f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } else { 83588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey summary.setVisibility(View.INVISIBLE); 83688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } 837251097b3789632000ccdaf7fb7d66a82ff37d882Jeff Sharkey } 838b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 839b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 840f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (icon1 != null) icon1.setVisibility(View.GONE); 841f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (icon2 != null) icon2.setVisibility(View.GONE); 842f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 843f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (iconDrawable != null) { 844f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (hasLine1) { 845f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey icon1.setVisibility(View.VISIBLE); 846f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey icon1.setImageDrawable(iconDrawable); 847f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey } else { 848f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey icon2.setVisibility(View.VISIBLE); 849f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey icon2.setImageDrawable(iconDrawable); 850f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey } 851f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey } 852f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey 8535dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (docLastModified == -1) { 8549d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey date.setText(null); 8559d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } else { 8565dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey date.setText(formatTime(context, docLastModified)); 85728c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey hasLine2 = true; 8589d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 859b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 860b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey if (state.showSize) { 861b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey size.setVisibility(View.VISIBLE); 8625dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey if (Document.MIME_TYPE_DIR.equals(docMimeType) || docSize == -1) { 863b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey size.setText(null); 864b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } else { 8655dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey size.setText(Formatter.formatFileSize(context, docSize)); 86628c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey hasLine2 = true; 867b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 868b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } else { 869b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey size.setVisibility(View.GONE); 87054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 871ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey 872f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (line1 != null) { 873f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey line1.setVisibility(hasLine1 ? View.VISIBLE : View.GONE); 874f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey } 87588f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey if (line2 != null) { 87688f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey line2.setVisibility(hasLine2 ? View.VISIBLE : View.GONE); 87788f322c3115e85bb96fb46f9192b5daecd472c64Jeff Sharkey } 87828c05ee8931cecf4c51c470e0043d30196010c49Jeff Sharkey 8793f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey final boolean enabled = Document.MIME_TYPE_DIR.equals(docMimeType) 8803f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey || MimePredicate.mimeMatches(state.acceptMimes, docMimeType); 8813f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey if (enabled) { 8823f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey setEnabledRecursive(convertView, true); 8833f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey icon.setAlpha(1f); 884f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (icon1 != null) icon1.setAlpha(1f); 885f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (icon2 != null) icon2.setAlpha(1f); 8863f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } else { 8873f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey setEnabledRecursive(convertView, false); 8883f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey icon.setAlpha(0.5f); 889f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (icon1 != null) icon1.setAlpha(0.5f); 890f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (icon2 != null) icon2.setAlpha(0.5f); 8913f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 8923f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 893ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey return convertView; 89454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey } 89554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 896ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey @Override 897ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey public int getCount() { 898954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey return mCursorCount + mFooters.size(); 899ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 9009e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey 901ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey @Override 9025dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey public Cursor getItem(int position) { 903954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (position < mCursorCount) { 9045dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey mCursor.moveToPosition(position); 905954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey return mCursor; 906954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } else { 907954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey return null; 9085dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey } 909ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 91054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey 911ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey @Override 912ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey public long getItemId(int position) { 9135dfb345df7cb17b3a7e534a80a270b4afe7934daJeff Sharkey return position; 914ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey } 915954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey 916954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey @Override 9173f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey public int getViewTypeCount() { 9183f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey return 4; 9193f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 9203f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 9213f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey @Override 922954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey public int getItemViewType(int position) { 923954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey if (position < mCursorCount) { 924954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey return 0; 925954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } else { 9263f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey position -= mCursorCount; 9273f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey return mFooters.get(position).getItemViewType(); 928954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 929954be0232655d316bc5decbbd35579af902c75c2Jeff Sharkey } 9309e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey } 9319d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9329d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> { 9334ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey private final Uri mUri; 9344ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey private final ImageView mIconMime; 9354ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey private final ImageView mIconThumb; 9364eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey private final Point mThumbSize; 9374ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey private final CancellationSignal mSignal; 9389d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9394ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey public ThumbnailAsyncTask( 9404ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey Uri uri, ImageView iconMime, ImageView iconThumb, Point thumbSize) { 9414ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mUri = uri; 9424ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mIconMime = iconMime; 9434ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mIconThumb = iconThumb; 9444eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey mThumbSize = thumbSize; 9454ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mSignal = new CancellationSignal(); 9469d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 9479d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9484ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey public void reallyCancel() { 9494ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey cancel(false); 9504ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mSignal.cancel(); 9519d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 9529d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9539d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey @Override 9549d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey protected Bitmap doInBackground(Uri... params) { 9554ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey final Context context = mIconThumb.getContext(); 9569d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9579d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey Bitmap result = null; 9589d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey try { 9594ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey // TODO: switch to using unstable provider 960ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkey result = DocumentsContract.getDocumentThumbnail( 9614ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey context.getContentResolver(), mUri, mThumbSize, mSignal); 9629d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey if (result != null) { 9634eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache( 9644eb407a832b7d6a2d62a535e5cab70b00a0bc8edJeff Sharkey context, mThumbSize); 9654ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey thumbs.put(mUri, result); 9669d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 9679d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } catch (Exception e) { 9689d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey Log.w(TAG, "Failed to load thumbnail: " + e); 9699d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 9709d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey return result; 9719d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 9729d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9739d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey @Override 9749d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey protected void onPostExecute(Bitmap result) { 9754ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey if (mIconThumb.getTag() == this && result != null) { 9764ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mIconThumb.setTag(null); 9774ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mIconThumb.setImageBitmap(result); 9784ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey 9794ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mIconMime.setAlpha(1f); 9804ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mIconMime.animate().alpha(0f).start(); 9814ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mIconThumb.setAlpha(0f); 9824ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey mIconThumb.animate().alpha(1f).start(); 9839d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 9849d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 9859d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 9869d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9879d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey private static String formatTime(Context context, long when) { 9889d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey // TODO: DateUtils should make this easier 9899d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey Time then = new Time(); 9909d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey then.set(when); 9919d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey Time now = new Time(); 9929d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey now.setToNow(); 9939d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9949d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey int flags = DateUtils.FORMAT_NO_NOON | DateUtils.FORMAT_NO_MIDNIGHT 9959d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey | DateUtils.FORMAT_ABBREV_ALL; 9969d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 9979d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey if (then.year != now.year) { 9989d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey flags |= DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE; 9999d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } else if (then.yearDay != now.yearDay) { 10009d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey flags |= DateUtils.FORMAT_SHOW_DATE; 10019d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } else { 10029d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey flags |= DateUtils.FORMAT_SHOW_TIME; 10039d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 10049d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey 10059d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey return DateUtils.formatDateTime(context, when, flags); 10069d0843df7e3984293dc4ab6ee2f9502e898b63aaJeff Sharkey } 1007b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 1008b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey private String findCommonMimeType(List<String> mimeTypes) { 1009b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey String[] commonType = mimeTypes.get(0).split("/"); 1010b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey if (commonType.length != 2) { 1011b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey return "*/*"; 1012b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey } 1013b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 1014b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey for (int i = 1; i < mimeTypes.size(); i++) { 1015b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey String[] type = mimeTypes.get(i).split("/"); 1016b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey if (type.length != 2) continue; 1017b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 1018b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey if (!commonType[1].equals(type[1])) { 1019b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey commonType[1] = "*"; 1020b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey } 1021b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 1022b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey if (!commonType[0].equals(type[0])) { 1023b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey commonType[0] = "*"; 1024b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey commonType[1] = "*"; 1025b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey break; 1026b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey } 1027b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey } 1028b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey 1029b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey return commonType[0] + "/" + commonType[1]; 1030b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey } 10313f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 10323f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey private void setEnabledRecursive(View v, boolean enabled) { 1033f6db154975ef575479ba4ab59d80bcf592288252Jeff Sharkey if (v == null) return; 10343f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey if (v.isEnabled() == enabled) return; 10353f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey v.setEnabled(enabled); 10363f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 10373f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey if (v instanceof ViewGroup) { 10383f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey final ViewGroup vg = (ViewGroup) v; 10393f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey for (int i = vg.getChildCount() - 1; i >= 0; i--) { 10403f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey setEnabledRecursive(vg.getChildAt(i), enabled); 10413f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 10423f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 10433f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 10449e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey} 1045