• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.documentsui.dirlist;
18 
19 import static com.android.documentsui.base.DocumentInfo.getCursorInt;
20 import static com.android.documentsui.base.DocumentInfo.getCursorString;
21 import static com.android.documentsui.base.State.MODE_GRID;
22 import static com.android.documentsui.base.State.MODE_LIST;
23 
24 import android.database.Cursor;
25 import android.provider.DocumentsContract.Document;
26 import android.support.v7.widget.RecyclerView;
27 import android.util.Log;
28 import android.view.ViewGroup;
29 
30 import com.android.documentsui.Model;
31 import com.android.documentsui.Model.Update;
32 import com.android.documentsui.base.EventListener;
33 import com.android.documentsui.base.Lookup;
34 import com.android.documentsui.base.State;
35 import com.android.documentsui.selection.SelectionHelper;
36 
37 import java.util.ArrayList;
38 import java.util.List;
39 
40 /**
41  * Adapts from dirlist.Model to something RecyclerView understands.
42  */
43 final class ModelBackedDocumentsAdapter extends DocumentsAdapter {
44 
45     private static final String TAG = "ModelBackedDocuments";
46 
47     // Provides access to information needed when creating and view holders. This
48     // isn't an ideal pattern (more transitive dependency stuff) but good enough for now.
49     private final Environment mEnv;
50     private final IconHelper mIconHelper;  // a transitive dependency of the holders.
51     private final Lookup<String, String> mFileTypeLookup;
52 
53     /**
54      * An ordered list of model IDs. This is the data structure that determines what shows up in
55      * the UI, and where.
56      */
57     private List<String> mModelIds = new ArrayList<>();
58     private EventListener<Model.Update> mModelUpdateListener;
59 
ModelBackedDocumentsAdapter( Environment env, IconHelper iconHelper, Lookup<String, String> fileTypeLookup)60     public ModelBackedDocumentsAdapter(
61             Environment env, IconHelper iconHelper, Lookup<String, String> fileTypeLookup) {
62         mEnv = env;
63         mIconHelper = iconHelper;
64         mFileTypeLookup = fileTypeLookup;
65 
66         mModelUpdateListener = new EventListener<Model.Update>() {
67             @Override
68             public void accept(Update event) {
69                 if (event.hasException()) {
70                     onModelUpdateFailed(event.getException());
71                 } else {
72                     onModelUpdate(mEnv.getModel());
73                 }
74             }
75         };
76     }
77 
78     @Override
getModelUpdateListener()79     EventListener<Update> getModelUpdateListener() {
80         return mModelUpdateListener;
81     }
82 
83     @Override
onCreateViewHolder(ViewGroup parent, int viewType)84     public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
85         DocumentHolder holder = null;
86         final State state = mEnv.getDisplayState();
87         switch (state.derivedMode) {
88             case MODE_GRID:
89                 switch (viewType) {
90                     case ITEM_TYPE_DIRECTORY:
91                         holder = new GridDirectoryHolder(mEnv.getContext(), parent);
92                         break;
93                     case ITEM_TYPE_DOCUMENT:
94                         holder = new GridDocumentHolder(mEnv.getContext(), parent, mIconHelper);
95                         break;
96                     default:
97                         throw new IllegalStateException("Unsupported layout type.");
98                 }
99                 break;
100             case MODE_LIST:
101                 holder = new ListDocumentHolder(
102                         mEnv.getContext(), parent, mIconHelper, mFileTypeLookup);
103                 break;
104             default:
105                 throw new IllegalStateException("Unsupported layout mode.");
106         }
107 
108         mEnv.initDocumentHolder(holder);
109         return holder;
110     }
111 
112     @Override
onBindViewHolder(DocumentHolder holder, int position, List<Object> payload)113     public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
114         if (payload.contains(SelectionHelper.SELECTION_CHANGED_MARKER)) {
115             final boolean selected = mEnv.isSelected(mModelIds.get(position));
116             holder.setSelected(selected, true);
117         } else {
118             onBindViewHolder(holder, position);
119         }
120     }
121 
122     @Override
onBindViewHolder(DocumentHolder holder, int position)123     public void onBindViewHolder(DocumentHolder holder, int position) {
124         String modelId = mModelIds.get(position);
125         Cursor cursor = mEnv.getModel().getItem(modelId);
126         holder.bind(cursor, modelId);
127 
128         final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
129         final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
130 
131         boolean enabled = mEnv.isDocumentEnabled(docMimeType, docFlags);
132         boolean selected = mEnv.isSelected(modelId);
133         if (!enabled) {
134             assert(!selected);
135         }
136         holder.setEnabled(enabled);
137         holder.setSelected(mEnv.isSelected(modelId), false);
138 
139         mEnv.onBindDocumentHolder(holder, cursor);
140     }
141 
142     @Override
getItemCount()143     public int getItemCount() {
144         return mModelIds.size();
145     }
146 
onModelUpdate(Model model)147     private void onModelUpdate(Model model) {
148         String[] modelIds = model.getModelIds();
149         mModelIds = new ArrayList<>(modelIds.length);
150         for (String id : modelIds) {
151             mModelIds.add(id);
152         }
153     }
154 
onModelUpdateFailed(Exception e)155     private void onModelUpdateFailed(Exception e) {
156         Log.w(TAG, "Model update failed.", e);
157         mModelIds.clear();
158     }
159 
160     @Override
getStableId(int adapterPosition)161     public String getStableId(int adapterPosition) {
162         return mModelIds.get(adapterPosition);
163     }
164 
165     @Override
getAdapterPosition(String modelId)166     public int getAdapterPosition(String modelId) {
167         return mModelIds.indexOf(modelId);
168     }
169 
170     @Override
getStableIds()171     public List<String> getStableIds() {
172         return mModelIds;
173     }
174 
175     @Override
getPosition(String id)176     public int getPosition(String id) {
177         int position = mModelIds.indexOf(id);
178         return position >= 0 ? position : RecyclerView.NO_POSITION;
179     }
180 
181     @Override
getItemViewType(int position)182     public int getItemViewType(int position) {
183         return isDirectory(mEnv.getModel(), position)
184                 ? ITEM_TYPE_DIRECTORY
185                 : ITEM_TYPE_DOCUMENT;
186     }
187 
188     /**
189      * @return true if the item type is either document or directory, false for all other
190      * possible types.
191      */
isContentType(int type)192     public static boolean isContentType(int type) {
193         switch (type) {
194             case ModelBackedDocumentsAdapter.ITEM_TYPE_DOCUMENT:
195             case ModelBackedDocumentsAdapter.ITEM_TYPE_DIRECTORY:
196                 return true;
197         }
198         return false;
199     }
200 }
201