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