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.getCursorString;
20 
21 import android.content.Context;
22 import android.database.Cursor;
23 import android.graphics.Rect;
24 import android.text.format.Formatter;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.widget.ImageView;
28 import android.widget.LinearLayout;
29 import android.widget.TextView;
30 
31 import com.android.documentsui.R;
32 import com.android.documentsui.base.DocumentInfo;
33 import com.android.documentsui.base.Events.InputEvent;
34 import com.android.documentsui.base.Shared;
35 import com.android.documentsui.roots.RootCursorWrapper;
36 
37 final class ListDocumentHolder extends DocumentHolder {
38 
39     private final TextView mTitle;
40     private final LinearLayout mDetails;  // Container of date/size/summary
41     private final TextView mDate;
42     private final TextView mSize;
43     private final TextView mSummary;
44     private final ImageView mIconMime;
45     private final ImageView mIconThumb;
46     private final ImageView mIconCheck;
47     private final IconHelper mIconHelper;
48     private final View mIconLayout;
49     // This is used in as a convenience in our bind method.
50     private final DocumentInfo mDoc;
51 
ListDocumentHolder(Context context, ViewGroup parent, IconHelper iconHelper)52     public ListDocumentHolder(Context context, ViewGroup parent, IconHelper iconHelper) {
53         super(context, parent, R.layout.item_doc_list);
54 
55         mIconLayout = itemView.findViewById(android.R.id.icon);
56         mIconMime = (ImageView) itemView.findViewById(R.id.icon_mime);
57         mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb);
58         mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check);
59         mTitle = (TextView) itemView.findViewById(android.R.id.title);
60         mSummary = (TextView) itemView.findViewById(android.R.id.summary);
61         mSize = (TextView) itemView.findViewById(R.id.size);
62         mDate = (TextView) itemView.findViewById(R.id.date);
63         // Warning: mDetails view doesn't exists in layout-sw720dp-land layout
64         mDetails = (LinearLayout) itemView.findViewById(R.id.line2);
65 
66         mIconHelper = iconHelper;
67         mDoc = new DocumentInfo();
68     }
69 
70     @Override
setSelected(boolean selected, boolean animate)71     public void setSelected(boolean selected, boolean animate) {
72         // We always want to make sure our check box disappears if we're not selected,
73         // even if the item is disabled. But it should be an error (see assert below)
74         // to be set to selected && be disabled.
75         float checkAlpha = selected ? 1f : 0f;
76         if (animate) {
77             fade(mIconCheck, checkAlpha).start();
78         } else {
79             mIconCheck.setAlpha(checkAlpha);
80         }
81 
82         if (!itemView.isEnabled()) {
83             assert(!selected);
84             return;
85         }
86 
87         super.setSelected(selected, animate);
88 
89         if (animate) {
90             fade(mIconMime, 1f - checkAlpha).start();
91             fade(mIconThumb, 1f - checkAlpha).start();
92         } else {
93             mIconMime.setAlpha(1f - checkAlpha);
94             mIconThumb.setAlpha(1f - checkAlpha);
95         }
96     }
97 
98     @Override
setEnabled(boolean enabled)99     public void setEnabled(boolean enabled) {
100         super.setEnabled(enabled);
101 
102         // Text colors enabled/disabled is handle via a color set.
103         final float imgAlpha = enabled ? 1f : DISABLED_ALPHA;
104         mIconMime.setAlpha(imgAlpha);
105         mIconThumb.setAlpha(imgAlpha);
106     }
107 
108     @Override
isInDragHotspot(InputEvent event)109     public boolean isInDragHotspot(InputEvent event) {
110         // If itemView is activated = selected, then whole region is interactive
111         if (itemView.isActivated()) {
112             return true;
113         }
114 
115         // Do everything in global coordinates - it makes things simpler.
116         int[] coords = new int[2];
117         mIconLayout.getLocationOnScreen(coords);
118 
119         Rect textBounds = new Rect();
120         mTitle.getPaint().getTextBounds(
121                 mTitle.getText().toString(), 0, mTitle.getText().length(), textBounds);
122 
123         Rect rect = new Rect(
124                 coords[0],
125                 coords[1],
126                 coords[0] + mIconLayout.getWidth() + textBounds.width(),
127                 coords[1] + Math.max(mIconLayout.getHeight(), textBounds.height()));
128 
129         // If the tap occurred inside icon or the text, these are interactive spots.
130         return rect.contains((int) event.getRawX(), (int) event.getRawY());
131     }
132 
133     /**
134      * Bind this view to the given document for display.
135      * @param cursor Pointing to the item to be bound.
136      * @param modelId The model ID of the item.
137      * @param state Current display state.
138      */
139     @Override
bind(Cursor cursor, String modelId)140     public void bind(Cursor cursor, String modelId) {
141         assert(cursor != null);
142 
143         mModelId = modelId;
144 
145         mDoc.updateFromCursor(cursor, getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY));
146 
147         mIconHelper.stopLoading(mIconThumb);
148 
149         mIconMime.animate().cancel();
150         mIconMime.setAlpha(1f);
151         mIconThumb.animate().cancel();
152         mIconThumb.setAlpha(0f);
153 
154         mIconHelper.load(mDoc, mIconThumb, mIconMime, null);
155 
156         mTitle.setText(mDoc.displayName, TextView.BufferType.SPANNABLE);
157         mTitle.setVisibility(View.VISIBLE);
158 
159 
160         boolean hasDetails = false;
161         if (mDoc.isDirectory()) {
162             // Note, we don't show any details for any directory...ever.
163             hasDetails = false;
164         } else {
165             if (mDoc.summary != null) {
166                 hasDetails = true;
167                 mSummary.setText(mDoc.summary);
168                 mSummary.setVisibility(View.VISIBLE);
169             } else {
170                 mSummary.setVisibility(View.INVISIBLE);
171             }
172 
173             if (mDoc.lastModified > 0) {
174                 hasDetails = true;
175                 mDate.setText(Shared.formatTime(mContext, mDoc.lastModified));
176             } else {
177                 mDate.setText(null);
178             }
179 
180             if (mDoc.size > -1) {
181                 hasDetails = true;
182                 mSize.setVisibility(View.VISIBLE);
183                 mSize.setText(Formatter.formatFileSize(mContext, mDoc.size));
184             } else {
185                 mSize.setVisibility(View.GONE);
186             }
187         }
188 
189         // mDetails view doesn't exists in layout-sw720dp-land layout
190         if (mDetails != null) {
191             mDetails.setVisibility(hasDetails ? View.VISIBLE : View.GONE);
192         }
193 
194         // TODO: Add document debug info
195         // Call includeDebugInfo
196     }
197 }
198