RecentsCreateFragment.java revision 845fe50423acd8e279ef37888f674deb52fd5fe1
1b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey/* 2b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project 3b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * 4b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * you may not use this file except in compliance with the License. 6b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * You may obtain a copy of the License at 7b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * 8b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * 10b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * Unless required by applicable law or agreed to in writing, software 11b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * See the License for the specific language governing permissions and 14b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * limitations under the License. 15b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey */ 16b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 17b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeypackage com.android.documentsui; 18b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 1958efce36cd1b26006e08ddd696292bf06fc34c81Steve McKayimport static com.android.documentsui.Shared.TAG; 20845fe50423acd8e279ef37888f674deb52fd5fe1Ben Linimport static com.android.documentsui.State.ACTION_CREATE; 210c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey 22b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.app.Fragment; 23b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.app.FragmentManager; 24b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.app.FragmentTransaction; 25b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.app.LoaderManager.LoaderCallbacks; 26b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.content.ContentResolver; 27b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.content.Context; 28b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.content.Loader; 29b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.database.Cursor; 303f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkeyimport android.graphics.drawable.Drawable; 31b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.net.Uri; 32b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.os.Bundle; 33b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.os.CancellationSignal; 34c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKayimport android.support.annotation.Nullable; 35c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKayimport android.support.v7.widget.LinearLayoutManager; 36c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKayimport android.support.v7.widget.RecyclerView; 373f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkeyimport android.text.Spannable; 383f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkeyimport android.text.SpannableStringBuilder; 39b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.text.TextUtils.TruncateAt; 403f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkeyimport android.text.style.ImageSpan; 410c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkeyimport android.util.Log; 42b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.view.LayoutInflater; 43c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKayimport android.view.MotionEvent; 44b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.view.View; 45b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.view.ViewGroup; 46b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.widget.ImageView; 47b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport android.widget.TextView; 48b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 49d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkeyimport com.android.documentsui.RecentsProvider.RecentColumns; 50b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport com.android.documentsui.model.DocumentStack; 516a20e574116af1072782c1e87cb03eb33f05ec50Jeff Sharkeyimport com.android.documentsui.model.DurableUtils; 52deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkeyimport com.android.documentsui.model.RootInfo; 53b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 54b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport libcore.io.IoUtils; 55b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 56b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkeyimport java.io.IOException; 57b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport java.util.ArrayList; 58deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkeyimport java.util.Collection; 59b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeyimport java.util.List; 60b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 61b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey/** 62b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey * Display directories where recent creates took place. 63b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey */ 64b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkeypublic class RecentsCreateFragment extends Fragment { 65b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 666efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey private View mEmptyView; 67c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay private RecyclerView mRecView; 68b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey private DocumentStackAdapter mAdapter; 69b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey private LoaderCallbacks<List<DocumentStack>> mCallbacks; 70b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 71b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey private static final int LOADER_RECENTS = 3; 72b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 73b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey public static void show(FragmentManager fm) { 74b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final RecentsCreateFragment fragment = new RecentsCreateFragment(); 75b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final FragmentTransaction ft = fm.beginTransaction(); 76b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey ft.replace(R.id.container_directory, fragment); 77b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey ft.commitAllowingStateLoss(); 78b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 79b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 80b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey @Override 81b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey public View onCreateView( 82b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 83b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final Context context = inflater.getContext(); 84b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 85b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final View view = inflater.inflate(R.layout.fragment_directory, container, false); 86b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 872036dad877336bf4d81202c334b1f2c81462bd9fBen Kwa mRecView = (RecyclerView) view.findViewById(R.id.dir_list); 88c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay mRecView.setLayoutManager(new LinearLayoutManager(getContext())); 89c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay mRecView.addOnItemTouchListener(mItemListener); 906efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 91c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay mEmptyView = view.findViewById(android.R.id.empty); 92b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 93b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey mAdapter = new DocumentStackAdapter(); 94c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay mRecView.setAdapter(mAdapter); 95b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 96deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey final RootsCache roots = DocumentsApplication.getRootsCache(context); 97e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay final State state = ((BaseActivity) getActivity()).getDisplayState(); 98deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey 99b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey mCallbacks = new LoaderCallbacks<List<DocumentStack>>() { 100b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey @Override 101b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey public Loader<List<DocumentStack>> onCreateLoader(int id, Bundle args) { 102deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey return new RecentsCreateLoader(context, roots, state); 103b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 104b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 105b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey @Override 106b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey public void onLoadFinished( 107b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey Loader<List<DocumentStack>> loader, List<DocumentStack> data) { 108c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay mAdapter.update(data); 109a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey 110a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey // When launched into empty recents, show drawer 111845fe50423acd8e279ef37888f674deb52fd5fe1Ben Lin if (mAdapter.isEmpty() && !state.hasLocationChanged() 112845fe50423acd8e279ef37888f674deb52fd5fe1Ben Lin && state.action != ACTION_CREATE 113845fe50423acd8e279ef37888f674deb52fd5fe1Ben Lin && context instanceof DocumentsActivity) { 114ef3e2cf35fbede340d5ff830b410baea8e461a94Steve McKay ((DocumentsActivity) context).setRootsDrawerOpen(true); 115a82c2e24bc226c123075331cdaafb171b3b07b85Jeff Sharkey } 116b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 117b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 118b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey @Override 119b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey public void onLoaderReset(Loader<List<DocumentStack>> loader) { 120c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay mAdapter.update(null); 121b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 122b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey }; 123b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 124b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey return view; 125b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 126b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 127b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey @Override 128b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey public void onStart() { 129b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey super.onStart(); 130b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey getLoaderManager().restartLoader(LOADER_RECENTS, getArguments(), mCallbacks); 131b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 132b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 133b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey @Override 134b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey public void onStop() { 135b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey super.onStop(); 136b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey getLoaderManager().destroyLoader(LOADER_RECENTS); 137b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 138b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 139c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay private RecyclerView.OnItemTouchListener mItemListener = 140c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay new RecyclerView.OnItemTouchListener() { 141c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay @Override 142c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 143c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay Events.MotionInputEvent event = new Events.MotionInputEvent(e, mRecView); 144c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay if (event.isOverItem() && event.isActionUp()) { 145c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay final DocumentStack stack = mAdapter.getItem(event.getItemPosition()); 146c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay ((BaseActivity) getActivity()).onStackPicked(stack); 147c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay return true; 148c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay } 149c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay return false; 150c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay } 151c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay 152c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay @Override 153c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay public void onTouchEvent(RecyclerView rv, MotionEvent e) {} 154c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay @Override 155c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {} 156c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay }; 157b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 158b448660a227f93d7bd5c5d019a21745e67c2f54dJeff Sharkey public static class RecentsCreateLoader extends UriDerivativeLoader<Uri, List<DocumentStack>> { 159deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey private final RootsCache mRoots; 160deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey private final State mState; 161deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey 162deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey public RecentsCreateLoader(Context context, RootsCache roots, State state) { 163d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey super(context, RecentsProvider.buildRecent()); 164deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey mRoots = roots; 165deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey mState = state; 166b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 167b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 168b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey @Override 169b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey public List<DocumentStack> loadInBackground(Uri uri, CancellationSignal signal) { 170deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey final Collection<RootInfo> matchingRoots = mRoots.getMatchingRootsBlocking(mState); 17158efce36cd1b26006e08ddd696292bf06fc34c81Steve McKay final ArrayList<DocumentStack> result = new ArrayList<>(); 172b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 173b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final ContentResolver resolver = getContext().getContentResolver(); 174b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final Cursor cursor = resolver.query( 175d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey uri, null, null, null, RecentColumns.TIMESTAMP + " DESC", signal); 176b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey try { 177b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey while (cursor != null && cursor.moveToNext()) { 178d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey final byte[] rawStack = cursor.getBlob( 179d182bb641f228b2d28527a6aa86075f6358ab838Jeff Sharkey cursor.getColumnIndex(RecentColumns.STACK)); 1800c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey try { 181b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey final DocumentStack stack = new DocumentStack(); 1826a20e574116af1072782c1e87cb03eb33f05ec50Jeff Sharkey DurableUtils.readFromArray(rawStack, stack); 183deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey 184deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey // Only update root here to avoid spinning up all 185deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey // providers; we update the stack during the actual 186deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey // restore. This also filters away roots that don't 187deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey // match current filter. 188deffadeb7485e8660ecce12822e259d96fa06dceJeff Sharkey stack.updateRoot(matchingRoots); 1890c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey result.add(stack); 190b51331116eb2ebbc41aaf69142916f9af6dffdd5Jeff Sharkey } catch (IOException e) { 1910c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey Log.w(TAG, "Failed to resolve stack: " + e); 1920c2d31bfa113c2848620ac05c916802410b71da1Jeff Sharkey } 193b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 194b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } finally { 195b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey IoUtils.closeQuietly(cursor); 196b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 197b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 198b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey return result; 199b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 200b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 201b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 202c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay private static final class StackHolder extends RecyclerView.ViewHolder { 203c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay public View view; 204c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay public StackHolder(View view) { 205c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay super(view); 206c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay this.view = view; 207c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay } 208c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay } 209c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay 210c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay private class DocumentStackAdapter extends RecyclerView.Adapter<StackHolder> { 211c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay @Nullable private List<DocumentStack> mItems; 212c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay 213c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay DocumentStack getItem(int position) { 214c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay return mItems.get(position); 215c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay } 216c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay 217c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay @Override 218c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay public int getItemCount() { 219c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay return mItems == null ? 0 : mItems.size(); 220c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay } 221b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 222c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay boolean isEmpty() { 223c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay return mItems == null ? true : mItems.isEmpty(); 224b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 225b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 226c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay void update(@Nullable List<DocumentStack> items) { 227c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay mItems = items; 2286efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 2296efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey if (isEmpty()) { 2306efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey mEmptyView.setVisibility(View.VISIBLE); 2316efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } else { 2326efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey mEmptyView.setVisibility(View.GONE); 2336efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey } 2346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey 235b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey notifyDataSetChanged(); 236b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 237b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 238b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey @Override 239c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay public StackHolder onCreateViewHolder(ViewGroup parent, int viewType) { 240c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay final Context context = parent.getContext(); 241b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 242c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay final LayoutInflater inflater = LayoutInflater.from(context); 243c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay return new StackHolder( 244c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay (View) inflater.inflate(R.layout.item_doc_list, parent, false)); 245c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay } 246c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay 247c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay @Override 248c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay public void onBindViewHolder(StackHolder holder, int position) { 249c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay Context context = getContext(); 250c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay View view = holder.view; 251b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 252c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay final ImageView iconMime = (ImageView) view.findViewById(R.id.icon_mime); 253c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay final TextView title = (TextView) view.findViewById(android.R.id.title); 254c643386e2801b7bb7f3ba79c4474a5b05a224d4fSteve McKay final View line2 = view.findViewById(R.id.line2); 255b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 256b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey final DocumentStack stack = getItem(position); 2574ec973925fc2cd18f9ec0d0ca5af588564fded27Jeff Sharkey iconMime.setImageDrawable(stack.root.loadIcon(context)); 258b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 25903d30a573b8bc8e169e153a0fffa053ffedcd5eeAlan Viverette final Drawable crumb = context.getDrawable(R.drawable.ic_breadcrumb_arrow); 2603f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey crumb.setBounds(0, 0, crumb.getIntrinsicWidth(), crumb.getIntrinsicHeight()); 2613f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 2623f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey final SpannableStringBuilder builder = new SpannableStringBuilder(); 2633f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey builder.append(stack.root.title); 2643f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey for (int i = stack.size() - 2; i >= 0; i--) { 2655545f56f7561810187545a1817b6001dd1f9931bJeff Sharkey appendDrawable(builder, crumb); 266b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey builder.append(stack.get(i).displayName); 267b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 2683f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey title.setText(builder); 269b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey title.setEllipsize(TruncateAt.MIDDLE); 270b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey 271f8abf2e387681f2ed7631783418972972379d740Jeff Sharkey if (line2 != null) line2.setVisibility(View.GONE); 272b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 273b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey } 2743f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey 2753f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey private static void appendDrawable(SpannableStringBuilder b, Drawable d) { 2763f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey final int length = b.length(); 2773f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey b.append("\u232a"); 2783f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey b.setSpan(new ImageSpan(d), length, b.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 2793f4c205fd3110345241e690f2a2e7c1b477eac76Jeff Sharkey } 280b156f4bf8cdfe475a7116b627d84a281e1a281b7Jeff Sharkey} 281