AttachmentTile.java revision 8081df46ef5a7794374e41cd1836e778a2da9b31
1/*
2 * Copyright (C) 2012 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.mail.ui;
19
20import android.content.ContentResolver;
21import android.content.Context;
22import android.graphics.Bitmap;
23import android.net.Uri;
24import android.os.Parcel;
25import android.os.Parcelable;
26import android.text.TextUtils;
27import android.util.AttributeSet;
28import android.view.View;
29import android.widget.ImageView;
30import android.widget.RelativeLayout;
31import android.widget.TextView;
32import android.widget.ImageView.ScaleType;
33
34import com.android.ex.photo.util.ImageUtils;
35import com.android.mail.R;
36import com.android.mail.providers.Attachment;
37import com.android.mail.utils.LogTag;
38import com.android.mail.utils.AttachmentUtils;
39import com.android.mail.utils.LogUtils;
40
41/**
42 * Base class for attachment tiles that handles the work of fetching and displaying the bitmaps for
43 * the tiles.
44 */
45public class AttachmentTile extends RelativeLayout implements AttachmentBitmapHolder {
46    protected Attachment mAttachment;
47    private ImageView mIcon;
48    private ImageView mDefaultIcon;
49    private ThumbnailLoadTask mThumbnailTask;
50    private TextView mTitle;
51    private TextView mSubtitle;
52    private String mAttachmentSizeText;
53    private String mDisplayType;
54    private boolean mDefaultThumbnailSet;
55    private AttachmentPreviewCache mAttachmentPreviewCache;
56
57    private static final String LOG_TAG = LogTag.getLogTag();
58
59    /**
60     * Returns true if the attachment should be rendered as a tile. with a large image preview.
61     * @param attachment the attachment to render
62     * @return true if the attachment should be rendered as a tile
63     */
64    public static boolean isTiledAttachment(final Attachment attachment) {
65        return ImageUtils.isImageMimeType(attachment.contentType);
66    }
67
68    public AttachmentTile(Context context) {
69        this(context, null);
70    }
71
72    public AttachmentTile(Context context, AttributeSet attrs) {
73        super(context, attrs);
74        mDefaultThumbnailSet = true;
75    }
76
77    @Override
78    protected void onFinishInflate() {
79        super.onFinishInflate();
80
81        mTitle = (TextView) findViewById(R.id.attachment_tile_title);
82        mSubtitle = (TextView) findViewById(R.id.attachment_tile_subtitle);
83        mIcon = (ImageView) findViewById(R.id.attachment_tile_image);
84        mDefaultIcon = (ImageView) findViewById(R.id.attachment_default_image);
85    }
86
87    @Override
88    protected void onLayout(boolean changed, int l, int t, int r, int b) {
89        super.onLayout(changed, l, t, r, b);
90
91        ThumbnailLoadTask.setupThumbnailPreview(mThumbnailTask, this, mAttachment, null);
92    }
93
94    /**
95     * Render or update an attachment's view. This happens immediately upon instantiation, and
96     * repeatedly as status updates stream in, so only properties with new or changed values will
97     * cause sub-views to update.
98     */
99    public void render(Attachment attachment, Uri attachmentsListUri, int index,
100            AttachmentPreviewCache attachmentPreviewCache, boolean loaderResult) {
101        if (attachment == null) {
102            setVisibility(View.INVISIBLE);
103            return;
104        }
105
106        final Attachment prevAttachment = mAttachment;
107        mAttachment = attachment;
108        mAttachmentPreviewCache = attachmentPreviewCache;
109
110        LogUtils.d(LOG_TAG, "got attachment list row: name=%s state/dest=%d/%d dled=%d" +
111                " contentUri=%s MIME=%s", attachment.name, attachment.state,
112                attachment.destination, attachment.downloadedSize, attachment.contentUri,
113                attachment.contentType);
114
115        if (prevAttachment == null || !TextUtils.equals(attachment.name, prevAttachment.name)) {
116            mTitle.setText(attachment.name);
117        }
118
119        if (prevAttachment == null || attachment.size != prevAttachment.size) {
120            mAttachmentSizeText = AttachmentUtils.convertToHumanReadableSize(getContext(),
121                    attachment.size);
122            mDisplayType = AttachmentUtils.getDisplayType(getContext(), attachment);
123            updateSubtitleText();
124        }
125
126        ThumbnailLoadTask.setupThumbnailPreview(mThumbnailTask, this, attachment, prevAttachment);
127    }
128
129    private void updateSubtitleText() {
130        // TODO: make this a formatted resource when we have a UX design.
131        // not worth translation right now.
132        StringBuilder sb = new StringBuilder();
133        sb.append(mAttachmentSizeText);
134        sb.append(' ');
135        sb.append(mDisplayType);
136        mSubtitle.setText(sb.toString());
137    }
138
139    @Override
140    public void setThumbnailToDefault() {
141        Bitmap cachedPreview = mAttachmentPreviewCache.get(mAttachment);
142        if (cachedPreview != null) {
143            setThumbnail(cachedPreview);
144            return;
145        }
146        mDefaultIcon.setVisibility(View.VISIBLE);
147        mDefaultThumbnailSet = true;
148    }
149
150    @Override
151    public void setThumbnail(Bitmap result) {
152        // We got a real thumbnail; hide the default thumbnail.
153        mDefaultIcon.setVisibility(View.GONE);
154        mIcon.setImageBitmap(result);
155        if (result.getWidth() < mIcon.getWidth() || result.getHeight() < mIcon.getHeight()) {
156            mIcon.setScaleType(ScaleType.CENTER);
157        } else {
158            mIcon.setScaleType(ScaleType.CENTER_CROP);
159        }
160        mAttachmentPreviewCache.set(mAttachment, result);
161        mDefaultThumbnailSet = false;
162    }
163
164    @Override
165    public int getThumbnailWidth() {
166        return mIcon.getWidth();
167    }
168
169    @Override
170    public int getThumbnailHeight() {
171        return mIcon.getHeight();
172    }
173
174    @Override
175    public ContentResolver getResolver() {
176        return getContext().getContentResolver();
177    }
178
179    @Override
180    public boolean bitmapSetToDefault() {
181        return mDefaultThumbnailSet;
182    }
183
184    public static final class AttachmentPreview implements Parcelable {
185        public String attachmentIdentifier;
186        public Bitmap preview;
187
188        @Override
189        public int describeContents() {
190            return 0;
191        }
192
193        @Override
194        public void writeToParcel(Parcel dest, int flags) {
195            dest.writeString(attachmentIdentifier);
196            dest.writeParcelable(preview, 0);
197        }
198
199        public static final Parcelable.Creator<AttachmentPreview> CREATOR
200                = new Parcelable.Creator<AttachmentPreview>() {
201                        @Override
202                    public AttachmentPreview createFromParcel(Parcel in) {
203                        return new AttachmentPreview(in);
204                    }
205
206                        @Override
207                    public AttachmentPreview[] newArray(int size) {
208                        return new AttachmentPreview[size];
209                    }
210                };
211
212        private AttachmentPreview(Parcel in) {
213            attachmentIdentifier = in.readString();
214            preview = in.readParcelable(null);
215        }
216
217        public AttachmentPreview(Attachment attachment, Bitmap preview) {
218            this.attachmentIdentifier = AttachmentUtils.getIdentifier(attachment);
219            this.preview = preview;
220        }
221    }
222
223    public interface AttachmentPreviewCache {
224        void set(Attachment attachment, Bitmap preview);
225        Bitmap get(Attachment attachment);
226    }
227}
228