MessageAttachmentTile.java revision aa27bc0e1c3bb6be4609b00007637a9d3e960f5e
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.browse; 19 20import android.app.FragmentManager; 21import android.content.ActivityNotFoundException; 22import android.content.Context; 23import android.content.Intent; 24import android.graphics.Bitmap; 25import android.net.Uri; 26import android.util.AttributeSet; 27import android.view.LayoutInflater; 28import android.view.View; 29import android.view.View.OnClickListener; 30import android.view.ViewGroup; 31import android.view.ViewParent; 32 33import com.android.ex.photo.util.ImageUtils; 34import com.android.mail.R; 35import com.android.mail.photo.MailPhotoViewActivity; 36import com.android.mail.providers.Attachment; 37import com.android.mail.providers.UIProvider; 38import com.android.mail.providers.UIProvider.AttachmentDestination; 39import com.android.mail.providers.UIProvider.AttachmentRendition; 40import com.android.mail.ui.AttachmentTile; 41import com.android.mail.ui.AttachmentTileGrid; 42import com.android.mail.utils.AttachmentUtils; 43import com.android.mail.utils.LogTag; 44import com.android.mail.utils.LogUtils; 45import com.android.mail.utils.Utils; 46 47import java.util.Comparator; 48import java.util.PriorityQueue; 49 50/** 51 * View for a single attachment in conversation view. Shows download status and allows launching 52 * intents to act on an attachment. 53 * 54 */ 55public class MessageAttachmentTile extends AttachmentTile implements OnClickListener, 56 AttachmentViewInterface { 57 58 private int mPhotoIndex; 59 private Uri mAttachmentsListUri; 60 private View mTextContainer; 61 62 private final AttachmentActionHandler mActionHandler; 63 64 private static final String LOG_TAG = LogTag.getLogTag(); 65 66 public MessageAttachmentTile(Context context) { 67 this(context, null); 68 } 69 70 public MessageAttachmentTile(Context context, AttributeSet attrs) { 71 super(context, attrs); 72 73 mActionHandler = new AttachmentActionHandler(context, this); 74 } 75 76 public void initialize(FragmentManager fragmentManager) { 77 mActionHandler.initialize(fragmentManager); 78 } 79 80 /** 81 * Render or update an attachment's view. This happens immediately upon instantiation, and 82 * repeatedly as status updates stream in, so only properties with new or changed values will 83 * cause sub-views to update. 84 */ 85 @Override 86 public void render(Attachment attachment, Uri attachmentsListUri, int index, 87 AttachmentPreviewCache attachmentPreviewCache, boolean loaderResult) { 88 super.render(attachment, attachmentsListUri, index, attachmentPreviewCache, loaderResult); 89 90 mAttachmentsListUri = attachmentsListUri; 91 mPhotoIndex = index; 92 93 mActionHandler.setAttachment(mAttachment); 94 mActionHandler.updateStatus(loaderResult); 95 } 96 97 public static MessageAttachmentTile inflate(LayoutInflater inflater, ViewGroup parent) { 98 MessageAttachmentTile view = (MessageAttachmentTile) inflater.inflate( 99 R.layout.conversation_message_attachment_tile, parent, false); 100 return view; 101 } 102 103 104 @Override 105 protected void onFinishInflate() { 106 super.onFinishInflate(); 107 108 mTextContainer = findViewById(R.id.attachment_tile_text_container); 109 110 setOnClickListener(this); 111 } 112 113 @Override 114 public void onClick(View v) { 115 onClick(); 116 } 117 118 private boolean onClick() { 119 showAndDownloadAttachments(); 120 return true; 121 } 122 123 private void showAndDownloadAttachments() { 124 AttachmentTileGrid tileGrid = ((AttachmentTileGrid) getParent()); 125 int childCount = tileGrid.getChildCount(); 126 127 PriorityQueue<MessageAttachmentTile> queue = new PriorityQueue<MessageAttachmentTile>( 128 childCount, new ViewIndexDistanceComparator(mPhotoIndex)); 129 for (int i = 0; i < childCount; i++) { 130 MessageAttachmentTile tile = (MessageAttachmentTile) tileGrid.getChildAt(i); 131 queue.add(tile); 132 } 133 134 // we want our downloads to have higher priority than the highest background downloads 135 int maxAdditionalPriority = childCount; 136 for (int i = 0; i < childCount; i++) { 137 // higher priority tiles are returned first 138 MessageAttachmentTile tile = queue.remove(); 139 tile.downloadAttachment(maxAdditionalPriority - i, i != 0); 140 } 141 142 viewAttachment(); 143 } 144 145 public void downloadAttachment(int additionalPriority, boolean delayDownload) { 146 if (!mAttachment.isPresentLocally()) { 147 mActionHandler.startDownloadingAttachment(AttachmentDestination.CACHE, 148 UIProvider.AttachmentRendition.BEST, additionalPriority, delayDownload); 149 } 150 } 151 152 @Override 153 public void viewAttachment() { 154 if (ImageUtils.isImageMimeType(Utils.normalizeMimeType(mAttachment.getContentType()))) { 155 MailPhotoViewActivity 156 .startMailPhotoViewActivity(getContext(), mAttachmentsListUri, mPhotoIndex); 157 return; 158 } 159 160 Intent intent = new Intent(Intent.ACTION_VIEW); 161 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION 162 | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 163 Utils.setIntentDataAndTypeAndNormalize( 164 intent, mAttachment.contentUri, mAttachment.getContentType()); 165 try { 166 getContext().startActivity(intent); 167 } catch (ActivityNotFoundException e) { 168 // couldn't find activity for View intent 169 LogUtils.e(LOG_TAG, "Couldn't find Activity for intent", e); 170 } 171 } 172 173 @Override 174 public void updateProgress(boolean showDeterminateProgress) { 175 // do not show progress for image tiles 176 } 177 178 @Override 179 public void onUpdateStatus() { 180 } 181 182 @Override 183 public void setThumbnailToDefault() { 184 super.setThumbnailToDefault(); 185 mTextContainer.setVisibility(VISIBLE); 186 } 187 188 @Override 189 public void setThumbnail(Bitmap result) { 190 super.setThumbnail(result); 191 mTextContainer.setVisibility(GONE); 192 } 193 194 @Override 195 public void thumbnailLoadFailed() { 196 super.thumbnailLoadFailed(); 197 198 if (AttachmentUtils.canDownloadAttachment(getContext(), null)) { 199 // Download if there is network. This check prevents the attachment 200 // download from failing and making the error toast show 201 mActionHandler.startDownloadingAttachment( 202 AttachmentDestination.CACHE, AttachmentRendition.SIMPLE, 0, false); 203 } 204 } 205 206 /** 207 * Given two child views, figure out whose index is closest to the specified 208 * index. 209 */ 210 public static class ViewIndexDistanceComparator implements Comparator<View>{ 211 final private int mIndex; 212 /** 213 * @param index Compare based on each view's distance to this index 214 */ 215 public ViewIndexDistanceComparator(int index) { 216 mIndex = index; 217 } 218 219 @Override 220 public int compare(View lhs, View rhs) { 221 ViewParent parent = lhs.getParent(); 222 if (parent == rhs.getParent()) { 223 if (parent instanceof ViewGroup) { 224 ViewGroup p = (ViewGroup) parent; 225 int lhsIndex = p.indexOfChild(lhs); 226 int rhsIndex = p.indexOfChild(rhs); 227 int lhsDistance = Math.abs(mIndex - lhsIndex); 228 int rhsDistance = Math.abs(mIndex - rhsIndex); 229 // prefer shorter distance since they are the next ones to be swiped to 230 int result = lhsDistance - rhsDistance; 231 if (result == 0) { 232 // prefer higher index since they are to the right in the photoviewer 233 return rhsIndex - lhsIndex; 234 } 235 return result; 236 } 237 } 238 return 0; 239 } 240 } 241} 242