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