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.getCursorLong;
21 import static com.android.documentsui.base.DocumentInfo.getCursorString;
22 
23 import android.content.Context;
24 import android.database.Cursor;
25 import android.provider.DocumentsContract.Document;
26 import android.text.format.Formatter;
27 import android.view.MotionEvent;
28 import android.view.View;
29 import android.view.ViewGroup;
30 import android.widget.ImageView;
31 import android.widget.TextView;
32 
33 import com.android.documentsui.R;
34 import com.android.documentsui.base.DocumentInfo;
35 import com.android.documentsui.base.Shared;
36 import com.android.documentsui.base.UserId;
37 import com.android.documentsui.roots.RootCursorWrapper;
38 import com.android.documentsui.ui.Views;
39 
40 import java.util.function.Function;
41 
42 final class GridDocumentHolder extends DocumentHolder {
43 
44     final TextView mTitle;
45     final TextView mDate;
46     final TextView mDetails;
47     final ImageView mIconMimeLg;
48     final ImageView mIconMimeSm;
49     final ImageView mIconThumb;
50     final ImageView mIconCheck;
51     final ImageView mIconBriefcase;
52     final IconHelper mIconHelper;
53     final View mIconLayout;
54     final View mPreviewIcon;
55 
56     // This is used in as a convenience in our bind method.
57     private final DocumentInfo mDoc = new DocumentInfo();
58 
GridDocumentHolder(Context context, ViewGroup parent, IconHelper iconHelper)59     public GridDocumentHolder(Context context, ViewGroup parent, IconHelper iconHelper) {
60         super(context, parent, R.layout.item_doc_grid);
61 
62         mIconLayout = itemView.findViewById(R.id.icon);
63         mTitle = (TextView) itemView.findViewById(android.R.id.title);
64         mDate = (TextView) itemView.findViewById(R.id.date);
65         mDetails = (TextView) itemView.findViewById(R.id.details);
66         mIconMimeLg = (ImageView) itemView.findViewById(R.id.icon_mime_lg);
67         mIconMimeSm = (ImageView) itemView.findViewById(R.id.icon_mime_sm);
68         mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb);
69         mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check);
70         mIconBriefcase = (ImageView) itemView.findViewById(R.id.icon_briefcase);
71         mPreviewIcon = itemView.findViewById(R.id.preview_icon);
72 
73         mIconHelper = iconHelper;
74     }
75 
76     @Override
setSelected(boolean selected, boolean animate)77     public void setSelected(boolean selected, boolean animate) {
78         // We always want to make sure our check box disappears if we're not selected,
79         // even if the item is disabled. This is because this object can be reused
80         // and this method will be called to setup initial state.
81         float checkAlpha = selected ? 1f : 0f;
82         if (animate) {
83             fade(mIconMimeSm, checkAlpha).start();
84             fade(mIconCheck, checkAlpha).start();
85         } else {
86             mIconCheck.setAlpha(checkAlpha);
87         }
88 
89         // But it should be an error to be set to selected && be disabled.
90         if (!itemView.isEnabled()) {
91             assert(!selected);
92         }
93 
94         super.setSelected(selected, animate);
95 
96         if (animate) {
97             fade(mIconMimeSm, 1f - checkAlpha).start();
98         } else {
99             mIconMimeSm.setAlpha(1f - checkAlpha);
100         }
101     }
102 
103     @Override
setEnabled(boolean enabled)104     public void setEnabled(boolean enabled) {
105         super.setEnabled(enabled);
106 
107         float imgAlpha = enabled ? 1f : DISABLED_ALPHA;
108 
109         mIconMimeLg.setAlpha(imgAlpha);
110         mIconMimeSm.setAlpha(imgAlpha);
111         mIconThumb.setAlpha(imgAlpha);
112     }
113 
114     @Override
bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback)115     public void bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback) {
116         mPreviewIcon.setVisibility(show ? View.VISIBLE : View.GONE);
117         if (show) {
118             mPreviewIcon.setContentDescription(
119                     itemView.getResources().getString(
120                             mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier())
121                                     ? R.string.preview_work_file
122                                     : R.string.preview_file, mDoc.displayName));
123             mPreviewIcon.setAccessibilityDelegate(new PreviewAccessibilityDelegate(clickCallback));
124         }
125     }
126 
127     @Override
bindBriefcaseIcon(boolean show)128     public void bindBriefcaseIcon(boolean show) {
129         mIconBriefcase.setVisibility(show ? View.VISIBLE : View.GONE);
130     }
131 
132     @Override
inDragRegion(MotionEvent event)133     public boolean inDragRegion(MotionEvent event) {
134      // Entire grid box should be draggable
135         return true;
136     }
137 
138     @Override
inSelectRegion(MotionEvent event)139     public boolean inSelectRegion(MotionEvent event) {
140         return Views.isEventOver(event, mIconLayout);
141     }
142 
143     @Override
inPreviewIconRegion(MotionEvent event)144     public boolean inPreviewIconRegion(MotionEvent event) {
145         return Views.isEventOver(event, mPreviewIcon);
146     }
147 
148     /**
149      * Bind this view to the given document for display.
150      * @param cursor Pointing to the item to be bound.
151      * @param modelId The model ID of the item.
152      */
153     @Override
bind(Cursor cursor, String modelId)154     public void bind(Cursor cursor, String modelId) {
155         assert(cursor != null);
156 
157         mModelId = modelId;
158 
159         mDoc.updateFromCursor(cursor,
160                 UserId.of(getCursorInt(cursor, RootCursorWrapper.COLUMN_USER_ID)),
161                 getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY));
162 
163         mIconHelper.stopLoading(mIconThumb);
164 
165         mIconMimeLg.animate().cancel();
166         mIconMimeLg.setAlpha(1f);
167         mIconThumb.animate().cancel();
168         mIconThumb.setAlpha(0f);
169 
170         mIconHelper.load(mDoc, mIconThumb, mIconMimeLg, mIconMimeSm);
171 
172         mTitle.setText(mDoc.displayName, TextView.BufferType.SPANNABLE);
173         mTitle.setVisibility(View.VISIBLE);
174 
175         // If file is partial, we want to show summary field as that's more relevant than fileSize
176         // and date
177         if (mDoc.isPartial()) {
178             final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY);
179             mDetails.setVisibility(View.VISIBLE);
180             mDate.setText(null);
181             mDetails.setText(docSummary);
182         } else {
183             if (mDoc.lastModified == -1) {
184                 mDate.setText(null);
185             } else {
186                 mDate.setText(Shared.formatTime(mContext, mDoc.lastModified));
187             }
188 
189             final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE);
190             if (mDoc.isDirectory() || docSize == -1) {
191                 mDetails.setVisibility(View.GONE);
192             } else {
193                 mDetails.setVisibility(View.VISIBLE);
194                 mDetails.setText(Formatter.formatFileSize(mContext, docSize));
195             }
196         }
197     }
198 }
199