blob: 921917c66a7f4c3beccb0cc09bb9db39e49108a9 [file] [log] [blame]
Steve McKayc5ecf892015-12-22 18:15:31 -08001/*
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
17package com.android.documentsui.dirlist;
18
Steve McKayd0805062016-09-15 14:30:38 -070019import static com.android.documentsui.base.DocumentInfo.getCursorInt;
20import static com.android.documentsui.base.DocumentInfo.getCursorString;
Steve McKayd9caa6a2016-09-15 16:36:45 -070021import static com.android.documentsui.base.State.MODE_GRID;
22import static com.android.documentsui.base.State.MODE_LIST;
Steve McKayc5ecf892015-12-22 18:15:31 -080023
24import android.database.Cursor;
25import android.provider.DocumentsContract.Document;
Steve McKayc5ecf892015-12-22 18:15:31 -080026import android.util.Log;
Steve McKayc5ecf892015-12-22 18:15:31 -080027import android.view.ViewGroup;
28
Garfield Tane9670332017-03-06 18:33:23 -080029import com.android.documentsui.Model;
Steve McKay990f76e2016-09-16 12:36:58 -070030import com.android.documentsui.base.EventListener;
Garfield Tanb47b4b52017-05-16 12:48:53 -070031import com.android.documentsui.base.Lookup;
Steve McKayd9caa6a2016-09-15 16:36:45 -070032import com.android.documentsui.base.State;
Garfield Tane9670332017-03-06 18:33:23 -080033import com.android.documentsui.Model.Update;
Steve McKayc5ecf892015-12-22 18:15:31 -080034
35import java.util.ArrayList;
Steve McKayc5ecf892015-12-22 18:15:31 -080036import java.util.List;
Steve McKayc5ecf892015-12-22 18:15:31 -080037
38/**
39 * Adapts from dirlist.Model to something RecyclerView understands.
40 */
41final class ModelBackedDocumentsAdapter extends DocumentsAdapter {
42
Ben Kwaf4b0ff62016-02-02 12:11:10 -080043 private static final String TAG = "ModelBackedDocuments";
Steve McKayc5ecf892015-12-22 18:15:31 -080044
45 // Provides access to information needed when creating and view holders. This
46 // isn't an ideal pattern (more transitive dependency stuff) but good enough for now.
47 private final Environment mEnv;
48 private final IconHelper mIconHelper; // a transitive dependency of the holders.
Garfield Tanb47b4b52017-05-16 12:48:53 -070049 private final Lookup<String, String> mFileTypeLookup;
Steve McKayc5ecf892015-12-22 18:15:31 -080050
51 /**
52 * An ordered list of model IDs. This is the data structure that determines what shows up in
53 * the UI, and where.
54 */
55 private List<String> mModelIds = new ArrayList<>();
Steve McKay990f76e2016-09-16 12:36:58 -070056 private EventListener<Model.Update> mModelUpdateListener;
Steve McKayc5ecf892015-12-22 18:15:31 -080057
Garfield Tanb47b4b52017-05-16 12:48:53 -070058 public ModelBackedDocumentsAdapter(
59 Environment env, IconHelper iconHelper, Lookup<String, String> fileTypeLookup) {
Steve McKayc5ecf892015-12-22 18:15:31 -080060 mEnv = env;
61 mIconHelper = iconHelper;
Garfield Tanb47b4b52017-05-16 12:48:53 -070062 mFileTypeLookup = fileTypeLookup;
Steve McKay990f76e2016-09-16 12:36:58 -070063
64 mModelUpdateListener = new EventListener<Model.Update>() {
65 @Override
66 public void accept(Update event) {
Ben Linf8f06e92017-01-27 17:15:48 -080067 if (event.hasException()) {
68 onModelUpdateFailed(event.getException());
Steve McKay990f76e2016-09-16 12:36:58 -070069 } else {
70 onModelUpdate(mEnv.getModel());
71 }
72 }
73 };
74 }
75
76 @Override
77 EventListener<Update> getModelUpdateListener() {
78 return mModelUpdateListener;
Steve McKayc5ecf892015-12-22 18:15:31 -080079 }
80
81 @Override
82 public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
83 DocumentHolder holder = null;
84 final State state = mEnv.getDisplayState();
85 switch (state.derivedMode) {
86 case MODE_GRID:
87 switch (viewType) {
88 case ITEM_TYPE_DIRECTORY:
89 holder = new GridDirectoryHolder(mEnv.getContext(), parent);
90 break;
91 case ITEM_TYPE_DOCUMENT:
92 holder = new GridDocumentHolder(mEnv.getContext(), parent, mIconHelper);
93 break;
94 default:
95 throw new IllegalStateException("Unsupported layout type.");
96 }
97 break;
98 case MODE_LIST:
Garfield Tanb47b4b52017-05-16 12:48:53 -070099 holder = new ListDocumentHolder(
100 mEnv.getContext(), parent, mIconHelper, mFileTypeLookup);
Steve McKayc5ecf892015-12-22 18:15:31 -0800101 break;
Steve McKayc5ecf892015-12-22 18:15:31 -0800102 default:
103 throw new IllegalStateException("Unsupported layout mode.");
104 }
105
106 mEnv.initDocumentHolder(holder);
107 return holder;
108 }
109
110 @Override
111 public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) {
112 if (payload.contains(SELECTION_CHANGED_MARKER)) {
113 final boolean selected = mEnv.isSelected(mModelIds.get(position));
Ben Kwa4c2f1a62016-03-16 12:13:21 -0700114 holder.setSelected(selected, true);
Steve McKayc5ecf892015-12-22 18:15:31 -0800115 } else {
116 onBindViewHolder(holder, position);
117 }
118 }
119
120 @Override
121 public void onBindViewHolder(DocumentHolder holder, int position) {
122 String modelId = mModelIds.get(position);
123 Cursor cursor = mEnv.getModel().getItem(modelId);
Steve McKay358c3ec2016-10-21 09:16:57 -0700124 holder.bind(cursor, modelId);
Steve McKayc5ecf892015-12-22 18:15:31 -0800125
126 final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
127 final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
128
Steve McKay2e744402016-03-08 11:37:22 -0800129 boolean enabled = mEnv.isDocumentEnabled(docMimeType, docFlags);
130 boolean selected = mEnv.isSelected(modelId);
131 if (!enabled) {
132 assert(!selected);
133 }
134 holder.setEnabled(enabled);
Ben Kwa4c2f1a62016-03-16 12:13:21 -0700135 holder.setSelected(mEnv.isSelected(modelId), false);
Steve McKayc5ecf892015-12-22 18:15:31 -0800136
137 mEnv.onBindDocumentHolder(holder, cursor);
138 }
139
140 @Override
141 public int getItemCount() {
142 return mModelIds.size();
143 }
144
Steve McKay990f76e2016-09-16 12:36:58 -0700145 private void onModelUpdate(Model model) {
Tomasz Mikolajewskif27c2742016-03-07 18:01:45 +0900146 String[] modelIds = model.getModelIds();
147 mModelIds = new ArrayList<>(modelIds.length);
Steve McKayc5ecf892015-12-22 18:15:31 -0800148 for (String id : modelIds) {
Ben Lin7b38f342016-12-14 11:52:35 -0800149 mModelIds.add(id);
Steve McKayc5ecf892015-12-22 18:15:31 -0800150 }
Steve McKayc5ecf892015-12-22 18:15:31 -0800151 }
152
Steve McKay990f76e2016-09-16 12:36:58 -0700153 private void onModelUpdateFailed(Exception e) {
Steve McKayc5ecf892015-12-22 18:15:31 -0800154 Log.w(TAG, "Model update failed.", e);
155 mModelIds.clear();
156 }
157
158 @Override
159 public String getModelId(int adapterPosition) {
160 return mModelIds.get(adapterPosition);
161 }
162
163 @Override
Jon Manned895582017-04-27 15:53:50 -0700164 public int getAdapterPosition(String modelId) {
165 return mModelIds.indexOf(modelId);
166 }
167
168 @Override
Steve McKayc5ecf892015-12-22 18:15:31 -0800169 public List<String> getModelIds() {
170 return mModelIds;
171 }
172
173 @Override
174 public int getItemViewType(int position) {
175 return isDirectory(mEnv.getModel(), position)
176 ? ITEM_TYPE_DIRECTORY
177 : ITEM_TYPE_DOCUMENT;
178 }
179
Steve McKay4f78ba62016-10-04 16:48:49 -0700180 /**
181 * @return true if the item type is either document or directory, false for all other
182 * possible types.
183 */
184 public static boolean isContentType(int type) {
185 switch (type) {
186 case ModelBackedDocumentsAdapter.ITEM_TYPE_DOCUMENT:
187 case ModelBackedDocumentsAdapter.ITEM_TYPE_DIRECTORY:
188 return true;
189 }
190 return false;
191 }
192
Steve McKayc5ecf892015-12-22 18:15:31 -0800193 @Override
Steve McKaye9104032016-01-05 12:53:35 -0800194 public void onItemSelectionChanged(String id) {
Steve McKayc5ecf892015-12-22 18:15:31 -0800195 int position = mModelIds.indexOf(id);
196
197 if (position >= 0) {
198 notifyItemChanged(position, SELECTION_CHANGED_MARKER);
199 } else {
200 Log.w(TAG, "Item change notification received for unknown item: " + id);
201 }
202 }
203}