DirectoryFragment.java revision a5599ef636e37cb0b6474349936999be1afe6987
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.Loader;
259e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.net.Uri;
269e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.os.Bundle;
279e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.provider.DocumentsContract;
2854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.text.format.DateUtils;
29b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.text.format.Formatter;
30be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.util.SparseBooleanArray;
31be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.view.ActionMode;
329e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.LayoutInflater;
3354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.Menu;
3454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.view.MenuItem;
359e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.View;
369e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.view.ViewGroup;
37be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.widget.AbsListView;
38be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport android.widget.AbsListView.MultiChoiceModeListener;
3954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.AdapterView;
4054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.AdapterView.OnItemClickListener;
41ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport android.widget.BaseAdapter;
4254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeyimport android.widget.GridView;
439e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.ImageView;
449e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.ListView;
459e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkeyimport android.widget.TextView;
469e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
471482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkeyimport com.android.documentsui.DocumentsActivity.DisplayState;
48ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport com.android.documentsui.model.Document;
49b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport com.android.documentsui.model.Root;
50ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport com.android.internal.util.Predicate;
51be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport com.google.android.collect.Lists;
52be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
53b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport java.text.DateFormat;
54be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkeyimport java.util.ArrayList;
55ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport java.util.Comparator;
56ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkeyimport java.util.List;
57b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport java.util.concurrent.atomic.AtomicInteger;
5854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
5954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey/**
6054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey * Display the documents inside a single directory.
6154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey */
6254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkeypublic class DirectoryFragment extends Fragment {
6354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
649fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    private View mEmptyView;
6554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    private ListView mListView;
6654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    private GridView mGridView;
6754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
68be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey    private AbsListView mCurrentView;
69be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
709fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey    private Predicate<Document> mFilter;
719fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
72ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    public static final int TYPE_NORMAL = 1;
73ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    public static final int TYPE_SEARCH = 2;
74ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    public static final int TYPE_RECENT_OPEN = 3;
75dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
76dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    private int mType = TYPE_NORMAL;
77dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey
789e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    private DocumentsAdapter mAdapter;
79ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    private LoaderCallbacks<List<Document>> mCallbacks;
809e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
81b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    private static final String EXTRA_TYPE = "type";
82dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey    private static final String EXTRA_URI = "uri";
839e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
84b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    private static AtomicInteger sLoaderId = new AtomicInteger(4000);
85b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
86b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    private final int mLoaderId = sLoaderId.incrementAndGet();
87b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
88b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public static void showNormal(FragmentManager fm, Uri uri) {
89b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        show(fm, TYPE_NORMAL, uri);
90b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    }
91b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
92b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public static void showSearch(FragmentManager fm, Uri uri, String query) {
93b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        final Uri searchUri = DocumentsContract.buildSearchUri(uri, query);
94b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        show(fm, TYPE_SEARCH, searchUri);
95b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    }
96b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
97b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public static void showRecentsOpen(FragmentManager fm) {
98b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        show(fm, TYPE_RECENT_OPEN, null);
99b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    }
1009e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
101b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    private static void show(FragmentManager fm, int type, Uri uri) {
1029e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        final Bundle args = new Bundle();
103b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        args.putInt(EXTRA_TYPE, type);
104dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        args.putParcelable(EXTRA_URI, uri);
1059e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1069e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        final DirectoryFragment fragment = new DirectoryFragment();
1079e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        fragment.setArguments(args);
1089e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1099e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        final FragmentTransaction ft = fm.beginTransaction();
11066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        ft.replace(R.id.container_directory, fragment);
1119e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        ft.commitAllowingStateLoss();
1129e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
1139e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
114ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    public static DirectoryFragment get(FragmentManager fm) {
115ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        // TODO: deal with multiple directories shown at once
11666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        return (DirectoryFragment) fm.findFragmentById(R.id.container_directory);
117ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    }
118ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
1199e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    @Override
1209e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    public View onCreateView(
1219e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
1229e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        final Context context = inflater.getContext();
1239e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
12454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        final View view = inflater.inflate(R.layout.fragment_directory, container, false);
12554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
1269fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        mEmptyView = view.findViewById(android.R.id.empty);
1279fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
12854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        mListView = (ListView) view.findViewById(R.id.list);
12954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        mListView.setOnItemClickListener(mItemListener);
130be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        mListView.setMultiChoiceModeListener(mMultiListener);
13154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
13254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        mGridView = (GridView) view.findViewById(R.id.grid);
13354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        mGridView.setOnItemClickListener(mItemListener);
134be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        mGridView.setMultiChoiceModeListener(mMultiListener);
13554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
136ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        mAdapter = new DocumentsAdapter();
13754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
138dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey        final Uri uri = getArguments().getParcelable(EXTRA_URI);
139b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        mType = getArguments().getInt(EXTRA_TYPE);
1409e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
141ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        mCallbacks = new LoaderCallbacks<List<Document>>() {
1429e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            @Override
143ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            public Loader<List<Document>> onCreateLoader(int id, Bundle args) {
1441482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey                final DisplayState state = getDisplayState(DirectoryFragment.this);
1459fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                mFilter = new MimePredicate(state.acceptMimes);
1461482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey
14754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                Uri contentsUri;
148dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                if (mType == TYPE_NORMAL) {
149dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                    contentsUri = DocumentsContract.buildContentsUri(uri);
150b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                } else if (mType == TYPE_RECENT_OPEN) {
151b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                    contentsUri = RecentsProvider.buildRecentOpen();
152bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                } else {
153dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                    contentsUri = uri;
154bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey                }
155bc2971d2499f5bf5534ced7296ece630ca902738Jeff Sharkey
15654ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                if (state.localOnly) {
15754ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                    contentsUri = DocumentsContract.setLocalOnly(contentsUri);
15854ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey                }
15954ca29a5b94c2edf461c5433825d4ae17469fd7cJeff Sharkey
160ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                final Comparator<Document> sortOrder;
161b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN) {
162ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                    sortOrder = new Document.DateComparator();
163ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                } else if (state.sortOrder == DisplayState.SORT_ORDER_NAME) {
164ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                    sortOrder = new Document.NameComparator();
1659fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                } else if (state.sortOrder == DisplayState.SORT_ORDER_SIZE) {
1669fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                    sortOrder = new Document.SizeComparator();
167ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                } else {
168ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                    throw new IllegalArgumentException("Unknown sort order " + state.sortOrder);
169ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                }
170ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
1719fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                return new DirectoryLoader(context, contentsUri, mType, null, sortOrder);
1729e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            }
1739e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1749e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            @Override
175ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            public void onLoadFinished(Loader<List<Document>> loader, List<Document> data) {
176ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                mAdapter.swapDocuments(data);
1779e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            }
1789e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1799e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            @Override
180ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            public void onLoaderReset(Loader<List<Document>> loader) {
181ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                mAdapter.swapDocuments(null);
1829e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            }
1839e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        };
1849e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
185b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        updateDisplayState();
186b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
18754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        return view;
1889e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
1899e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1909e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    @Override
1919e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    public void onStart() {
1929e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        super.onStart();
193b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks);
1949e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
1959e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
1969e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    @Override
1979e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    public void onStop() {
1989e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        super.onStop();
199b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        getLoaderManager().destroyLoader(mLoaderId);
20054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
2019e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
202b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey    public void updateDisplayState() {
2031482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        final DisplayState state = getDisplayState(this);
20454e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
2059fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey        // TODO: avoid kicking loader when nothing changed
206b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks);
207b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        mListView.smoothScrollToPosition(0);
208b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey        mGridView.smoothScrollToPosition(0);
20954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
2101482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        mListView.setVisibility(state.mode == DisplayState.MODE_LIST ? View.VISIBLE : View.GONE);
2111482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        mGridView.setVisibility(state.mode == DisplayState.MODE_GRID ? View.VISIBLE : View.GONE);
21254e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
213be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        final int choiceMode;
2141482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        if (state.allowMultiple) {
215be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL;
216be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        } else {
217be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            choiceMode = ListView.CHOICE_MODE_NONE;
218be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
219be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
2201482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        if (state.mode == DisplayState.MODE_GRID) {
22154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            mListView.setAdapter(null);
222be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
22354e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            mGridView.setAdapter(mAdapter);
224be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mGridView.setColumnWidth(getResources().getDimensionPixelSize(R.dimen.grid_width));
22554e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            mGridView.setNumColumns(GridView.AUTO_FIT);
226be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mGridView.setChoiceMode(choiceMode);
227be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mCurrentView = mGridView;
2281482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        } else if (state.mode == DisplayState.MODE_LIST) {
22954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            mGridView.setAdapter(null);
230be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
23154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            mListView.setAdapter(mAdapter);
232be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mListView.setChoiceMode(choiceMode);
233be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mCurrentView = mListView;
2341482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        } else {
2351482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey            throw new IllegalStateException();
23654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
23754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
23854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
23954e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    private OnItemClickListener mItemListener = new OnItemClickListener() {
24054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        @Override
24154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
242ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            final Document doc = mAdapter.getItem(position);
243a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            if (mFilter.apply(doc)) {
244a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                ((DocumentsActivity) getActivity()).onDocumentPicked(doc);
245a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey            }
24654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
24754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    };
24854e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
249be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey    private MultiChoiceModeListener mMultiListener = new MultiChoiceModeListener() {
250be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        @Override
251be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
252be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mode.getMenuInflater().inflate(R.menu.mode_directory, menu);
253be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            return true;
254be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
255be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
256be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        @Override
257be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
258be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            return true;
259be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
260be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
261be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        @Override
262be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
263be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            if (item.getItemId() == R.id.menu_open) {
264dc2963aecaf38bf53d6de82957412a486049c207Jeff Sharkey                final Uri uri = getArguments().getParcelable(EXTRA_URI);
265be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions();
266be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                final ArrayList<Document> docs = Lists.newArrayList();
267be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
268be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                final int size = checked.size();
269be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                for (int i = 0; i < size; i++) {
270be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                    if (checked.valueAt(i)) {
271ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                        final Document doc = mAdapter.getItem(checked.keyAt(i));
272ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                        docs.add(doc);
273be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                    }
274be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                }
275be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
276be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                ((DocumentsActivity) getActivity()).onDocumentsPicked(docs);
277be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                return true;
278be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            } else {
279be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                return false;
280be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            }
281be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
282be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
283be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        @Override
284be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        public void onDestroyActionMode(ActionMode mode) {
285be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            // ignored
286be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
287be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
288be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        @Override
289be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        public void onItemCheckedStateChanged(
290be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                ActionMode mode, int position, long id, boolean checked) {
291be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            if (checked) {
292be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                // Directories cannot be checked
293ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                final Document doc = mAdapter.getItem(position);
294b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                if (doc.isDirectory()) {
295be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                    mCurrentView.setItemChecked(position, false);
296be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                }
297be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            }
298be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
299be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey            mode.setTitle(getResources()
300be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey                    .getString(R.string.mode_selected_count, mCurrentView.getCheckedItemCount()));
301be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey        }
302be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey    };
303be8b12e687bd10a526b1f54c2d8a52abdad15d85Jeff Sharkey
3041482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey    private static DisplayState getDisplayState(Fragment fragment) {
3051482789374fb8da3abea8f6f4f272a67205b95dbJeff Sharkey        return ((DocumentsActivity) fragment.getActivity()).getDisplayState();
30654e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey    }
30754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
308ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey    private class DocumentsAdapter extends BaseAdapter {
309ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        private List<Document> mDocuments;
310ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
311ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public DocumentsAdapter() {
3129e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
3139e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
314ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public void swapDocuments(List<Document> documents) {
315ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            mDocuments = documents;
3169fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
3179fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            if (documents != null && documents.isEmpty()) {
3189fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                mEmptyView.setVisibility(View.VISIBLE);
3199fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            } else {
3209fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                mEmptyView.setVisibility(View.GONE);
3219fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
3229fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
323ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            notifyDataSetChanged();
3249e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        }
3259e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
3269e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey        @Override
327ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public View getView(int position, View convertView, ViewGroup parent) {
328ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            final Context context = parent.getContext();
329b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            final DisplayState state = getDisplayState(DirectoryFragment.this);
330ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
331ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            if (convertView == null) {
332ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                final LayoutInflater inflater = LayoutInflater.from(context);
333ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                if (state.mode == DisplayState.MODE_LIST) {
334ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                    convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
335ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                } else if (state.mode == DisplayState.MODE_GRID) {
336ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                    convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);
337ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                } else {
338ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                    throw new IllegalStateException();
339ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                }
340ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            }
341ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
342ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            final Document doc = getItem(position);
343ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
344b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
345ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
3469fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            final View summaryGrid = convertView.findViewById(R.id.summary_grid);
347b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1);
348ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
349b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            final TextView date = (TextView) convertView.findViewById(R.id.date);
350b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            final TextView size = (TextView) convertView.findViewById(R.id.size);
351ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
352ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            if (doc.isThumbnailSupported()) {
353ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                // TODO: load thumbnails async
354ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                icon.setImageURI(doc.uri);
3559e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            } else {
35666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey                icon.setImageDrawable(RootsCache.resolveDocumentIcon(
357ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey                        context, doc.uri.getAuthority(), doc.mimeType));
3589e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey            }
3599e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
360ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            title.setText(doc.displayName);
361b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
362b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            if (mType == TYPE_NORMAL || mType == TYPE_SEARCH) {
363b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                icon1.setVisibility(View.GONE);
364b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                if (doc.summary != null) {
365b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                    summary.setText(doc.summary);
366b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                    summary.setVisibility(View.VISIBLE);
367b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                } else {
368b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                    summary.setVisibility(View.INVISIBLE);
369b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                }
370b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            } else if (mType == TYPE_RECENT_OPEN) {
371b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                final Root root = RootsCache.findRoot(context, doc);
372b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                icon1.setVisibility(View.VISIBLE);
373b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                icon1.setImageDrawable(root.icon);
374b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                summary.setText(root.getDirectoryString());
375b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                summary.setVisibility(View.VISIBLE);
376b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            }
377b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
3789fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            if (summaryGrid != null) {
3799fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                summaryGrid.setVisibility(
3809fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey                        (summary.getVisibility() == View.VISIBLE) ? View.VISIBLE : View.GONE);
3819fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey            }
3829fb567b59112f99e64e0bff6f343188331bad28dJeff Sharkey
383b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            // TODO: omit year from format
384b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            date.setText(DateUtils.formatSameDayTime(
385b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                    doc.lastModified, System.currentTimeMillis(), DateFormat.SHORT,
386b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                    DateFormat.SHORT));
387b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey
388b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            if (state.showSize) {
389b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                size.setVisibility(View.VISIBLE);
390a5599ef636e37cb0b6474349936999be1afe6987Jeff Sharkey                if (doc.isDirectory() || doc.size == -1) {
391b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                    size.setText(null);
392b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                } else {
393b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                    size.setText(Formatter.formatFileSize(context, doc.size));
394b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                }
395b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey            } else {
396b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey                size.setVisibility(View.GONE);
39754e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey            }
398ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey
399ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            return convertView;
40054e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey        }
40154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
402ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        @Override
403ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public int getCount() {
404ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            return mDocuments != null ? mDocuments.size() : 0;
405ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        }
4069e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey
407ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        @Override
408ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public Document getItem(int position) {
409ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            return mDocuments.get(position);
410ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        }
41154e55b740fef1be654c3959aee41ef5ddfa61293Jeff Sharkey
412ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        @Override
413ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        public long getItemId(int position) {
414ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey            return getItem(position).uri.hashCode();
415ef7184a1aa0be5d496a5cb495a0f9e11f342af44Jeff Sharkey        }
4169e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey    }
4179e0036ed7d3260d79cc5f9ffd8e3bbe760699924Jeff Sharkey}
418