Merge "Compose now shows images as tiled attachments." into jb-ub-mail
diff --git a/res/layout/compose.xml b/res/layout/compose.xml
index 0d0b680..acbdc1f 100644
--- a/res/layout/compose.xml
+++ b/res/layout/compose.xml
@@ -56,8 +56,17 @@
android:paddingTop="2dip"
android:paddingRight="5dip"
android:paddingBottom="0dip"
- android:paddingLeft="5dip" />
-
+ android:paddingLeft="5dip">
+ <com.android.mail.ui.AttachmentTileGrid
+ android:id="@+id/attachment_tile_grid"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+ <LinearLayout
+ android:id="@+id/attachment_bar_list"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="vertical" />
+ </com.android.mail.compose.AttachmentsView>
<!-- Body -->
<include layout="@layout/compose_body"/>
diff --git a/res/layout/compose_attachment_tile.xml b/res/layout/compose_attachment_tile.xml
new file mode 100644
index 0000000..4ee830d
--- /dev/null
+++ b/res/layout/compose_attachment_tile.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2012 Google Inc.
+ Licensed to The Android Open Source Project.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<com.android.mail.compose.ComposeAttachmentTile
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/attachment_tile"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/attachment_bg_holo">
+
+ <ImageView
+ android:id="@+id/attachment_tile_image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop" />
+
+ <View
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:layout_width="48dip"
+ android:layout_height="48dip"
+ android:background="@color/black_semi_transparent" />
+ <ImageButton
+ android:id="@+id/attachment_tile_close_button"
+ android:src="@drawable/ic_cancel_holo_light"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:layout_width="48dip"
+ android:layout_height="48dip"
+ android:paddingTop="12dip"
+ android:paddingRight="12dip"
+ android:paddingBottom="12dip"
+ android:paddingLeft="12dip"
+ android:focusable="true"
+ android:background="?android:attr/selectableItemBackground" />
+
+</com.android.mail.compose.ComposeAttachmentTile>
diff --git a/res/layout/conversation_message_footer.xml b/res/layout/conversation_message_footer.xml
index 7ceedc7..b8b6ace 100644
--- a/res/layout/conversation_message_footer.xml
+++ b/res/layout/conversation_message_footer.xml
@@ -38,7 +38,7 @@
android:layout_marginBottom="2dip"
android:background="@android:color/holo_blue_light"
android:visibility="gone"/>
- <com.android.mail.browse.AttachmentTileGrid
+ <com.android.mail.ui.AttachmentTileGrid
android:id="@+id/attachment_tile_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 3f71f9a..77fd91d 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -44,6 +44,7 @@
<!-- Must match the quoted_text_background_color_string -->
<color name="compose_background_color">#ebebeb</color>
<string name="quoted_text_font_color_string" translatable="false">#777777</string>
+ <color name="black_semi_transparent">#77000000</color>
<color name="conv_header_add_label_text">@android:color/black</color>
<color name="conv_header_add_label_background">#eeeeee</color>
diff --git a/src/com/android/mail/browse/MessageAttachmentTile.java b/src/com/android/mail/browse/MessageAttachmentTile.java
index aaec720..cda46bb 100644
--- a/src/com/android/mail/browse/MessageAttachmentTile.java
+++ b/src/com/android/mail/browse/MessageAttachmentTile.java
@@ -20,20 +20,12 @@
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
-import android.content.res.AssetFileDescriptor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.net.Uri;
-import android.os.AsyncTask;
import android.util.AttributeSet;
import android.view.LayoutInflater;
-import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.PopupMenu.OnMenuItemClickListener;
-import android.widget.RelativeLayout;
import com.android.mail.R;
import com.android.mail.photo.Intents;
@@ -43,100 +35,25 @@
import com.android.mail.providers.Attachment;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.AttachmentDestination;
+import com.android.mail.ui.AttachmentTile;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
-import java.io.IOException;
-
/**
* View for a single attachment in conversation view. Shows download status and allows launching
* intents to act on an attachment.
*
*/
-public class MessageAttachmentTile extends RelativeLayout implements OnClickListener,
- OnMenuItemClickListener, AttachmentViewInterface {
+public class MessageAttachmentTile extends AttachmentTile implements OnClickListener,
+ AttachmentViewInterface {
- private Attachment mAttachment;
- private ImageView mIcon;
- private ImageView.ScaleType mIconScaleType;
private int mPhotoIndex;
private Uri mAttachmentsListUri;
private final AttachmentActionHandler mActionHandler;
- private ThumbnailLoadTask mThumbnailTask;
-
private static final String LOG_TAG = new LogUtils().getLogTag();
- private class ThumbnailLoadTask extends AsyncTask<Uri, Void, Bitmap> {
-
- private final int mWidth;
- private final int mHeight;
-
- public ThumbnailLoadTask(int width, int height) {
- mWidth = width;
- mHeight = height;
- }
-
- @Override
- protected Bitmap doInBackground(Uri... params) {
- final Uri thumbnailUri = params[0];
-
- AssetFileDescriptor fd = null;
- Bitmap result = null;
-
- try {
- fd = getContext().getContentResolver().openAssetFileDescriptor(thumbnailUri, "r");
- if (isCancelled() || fd == null) {
- return null;
- }
-
- final BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inJustDecodeBounds = true;
-
- BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, opts);
- if (isCancelled() || opts.outWidth == -1 || opts.outHeight == -1) {
- return null;
- }
-
- opts.inJustDecodeBounds = false;
-
- LogUtils.d(LOG_TAG, "in background, src w/h=%d/%d dst w/h=%d/%d, divider=%d",
- opts.outWidth, opts.outHeight, mWidth, mHeight, opts.inSampleSize);
-
- result = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, opts);
-
- } catch (Throwable t) {
- LogUtils.e(LOG_TAG, t, "Unable to decode thumbnail %s", thumbnailUri);
- } finally {
- if (fd != null) {
- try {
- fd.close();
- } catch (IOException e) {
- LogUtils.e(LOG_TAG, e, "");
- }
- }
- }
-
- return result;
- }
-
- @Override
- protected void onPostExecute(Bitmap result) {
- if (result == null) {
- LogUtils.d(LOG_TAG, "back in UI thread, decode failed");
- setThumbnailToDefault();
- return;
- }
-
- LogUtils.d(LOG_TAG, "back in UI thread, decode success, w/h=%d/%d", result.getWidth(),
- result.getHeight());
- mIcon.setImageBitmap(result);
- mIcon.setScaleType(mIconScaleType);
- }
-
- }
-
public MessageAttachmentTile(Context context) {
this(context, null);
}
@@ -147,12 +64,6 @@
mActionHandler = new AttachmentActionHandler(context, this);
}
- public static MessageAttachmentTile inflate(LayoutInflater inflater, ViewGroup parent) {
- MessageAttachmentTile view = (MessageAttachmentTile) inflater.inflate(
- R.layout.conversation_message_attachment_tile, parent, false);
- return view;
- }
-
/**
* Render or update an attachment's view. This happens immediately upon instantiation, and
* repeatedly as status updates stream in, so only properties with new or changed values will
@@ -160,58 +71,27 @@
*
*/
public void render(Attachment attachment, Uri attachmentsListUri, int index) {
- if (attachment == null) {
- setVisibility(View.INVISIBLE);
- return;
- }
+ super.render(attachment, attachmentsListUri, index);
- final Attachment prevAttachment = mAttachment;
- mAttachment = attachment;
- mActionHandler.setAttachment(mAttachment);
mAttachmentsListUri = attachmentsListUri;
mPhotoIndex = index;
- LogUtils.d(LOG_TAG, "got attachment list row: name=%s state/dest=%d/%d dled=%d" +
- " contentUri=%s MIME=%s", attachment.name, attachment.state,
- attachment.destination, attachment.downloadedSize, attachment.contentUri,
- attachment.contentType);
-
- final Uri imageUri = attachment.getImageUri();
- final Uri prevImageUri = (prevAttachment == null) ? null : prevAttachment.getImageUri();
- // begin loading a thumbnail if this is an image and either the thumbnail or the original
- // content is ready (and different from any existing image)
- if (imageUri != null && (prevImageUri == null || !imageUri.equals(prevImageUri))) {
- // cancel/dispose any existing task and start a new one
- if (mThumbnailTask != null) {
- mThumbnailTask.cancel(true);
- }
- mThumbnailTask = new ThumbnailLoadTask(mIcon.getWidth(), mIcon.getHeight());
- mThumbnailTask.execute(imageUri);
- } else if (imageUri == null) {
- // not an image, or no thumbnail exists. fall back to default.
- // async image load must separately ensure the default appears upon load failure.
- setThumbnailToDefault();
- }
-
+ mActionHandler.setAttachment(mAttachment);
mActionHandler.updateStatus();
}
- private void setThumbnailToDefault() {
- mIcon.setImageResource(R.drawable.ic_menu_attachment_holo_light);
- mIcon.setScaleType(ImageView.ScaleType.CENTER);
+ public static MessageAttachmentTile inflate(LayoutInflater inflater, ViewGroup parent) {
+ MessageAttachmentTile view = (MessageAttachmentTile) inflater.inflate(
+ R.layout.conversation_message_attachment_tile, parent, false);
+ return view;
}
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mIcon = (ImageView) findViewById(R.id.attachment_tile_image);
-
setOnClickListener(this);
-
- mIconScaleType = mIcon.getScaleType();
}
@Override
@@ -219,11 +99,6 @@
onClick(v.getId(), v);
}
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- return onClick(item.getItemId(), null);
- }
-
private boolean onClick(int res, View v) {
mActionHandler.showAttachment(AttachmentDestination.CACHE);
diff --git a/src/com/android/mail/browse/MessageFooterView.java b/src/com/android/mail/browse/MessageFooterView.java
index a925292..ca114e4 100644
--- a/src/com/android/mail/browse/MessageFooterView.java
+++ b/src/com/android/mail/browse/MessageFooterView.java
@@ -32,9 +32,10 @@
import com.android.mail.browse.AttachmentLoader.AttachmentCursor;
import com.android.mail.browse.ConversationContainer.DetachListener;
import com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem;
-import com.android.mail.photo.util.ImageUtils;
import com.android.mail.providers.Attachment;
import com.android.mail.providers.Message;
+import com.android.mail.ui.AttachmentTile;
+import com.android.mail.ui.AttachmentTileGrid;
import com.android.mail.utils.LogUtils;
import com.google.common.collect.Lists;
@@ -163,7 +164,7 @@
List<Attachment> barAttachments = new ArrayList<Attachment>(maxSize);
for (Attachment attachment : attachments) {
- if (isTiledAttachment(attachment)) {
+ if (AttachmentTile.isTiledAttachment(attachment)) {
tiledAttachments.add(attachment);
} else {
barAttachments.add(attachment);
@@ -202,10 +203,6 @@
}
}
- private boolean isTiledAttachment(final Attachment attachment) {
- return ImageUtils.isImageMimeType(attachment.contentType);
- }
-
private Integer getAttachmentLoaderId() {
Integer id = null;
final Message msg = mMessageHeaderItem == null ? null : mMessageHeaderItem.message;
diff --git a/src/com/android/mail/compose/AttachmentComposeView.java b/src/com/android/mail/compose/AttachmentComposeView.java
index 783b601..2067561 100644
--- a/src/com/android/mail/compose/AttachmentComposeView.java
+++ b/src/com/android/mail/compose/AttachmentComposeView.java
@@ -33,7 +33,7 @@
* This view is used in the ComposeActivity to display an attachment along with its name/size
* and a Remove button.
*/
-class AttachmentComposeView extends LinearLayout {
+class AttachmentComposeView extends LinearLayout implements AttachmentDeletionInterface {
private final Attachment mAttachment;
private final static String LOG_TAG = new LogUtils().getLogTag();
diff --git a/src/com/android/mail/compose/AttachmentDeletionInterface.java b/src/com/android/mail/compose/AttachmentDeletionInterface.java
new file mode 100644
index 0000000..c41a3f8
--- /dev/null
+++ b/src/com/android/mail/compose/AttachmentDeletionInterface.java
@@ -0,0 +1,18 @@
+
+package com.android.mail.compose;
+
+import android.view.View.OnClickListener;
+
+/**
+ * Interface for views in the compose layout that represent
+ * attachments so that the larger attachments view can set
+ * the onClickListener for the close button to remove the attachment
+ * from the draft.
+ */
+interface AttachmentDeletionInterface {
+ /**
+ * Sets the onClickListener for the close button on the attachment view.
+ * @param clickListener the listener to which the close button should be set
+ */
+ public void addDeleteListener(OnClickListener clickListener);
+}
diff --git a/src/com/android/mail/compose/AttachmentsView.java b/src/com/android/mail/compose/AttachmentsView.java
index 5cb4413..d1615c2 100644
--- a/src/com/android/mail/compose/AttachmentsView.java
+++ b/src/com/android/mail/compose/AttachmentsView.java
@@ -15,15 +15,6 @@
*/
package com.android.mail.compose;
-import com.android.mail.R;
-import com.android.mail.providers.Account;
-import com.android.mail.providers.Attachment;
-import com.android.mail.providers.Message;
-import com.android.mail.providers.UIProvider;
-import com.android.mail.utils.LogUtils;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
-
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
@@ -35,9 +26,21 @@
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Toast;
+import com.android.mail.R;
+import com.android.mail.providers.Account;
+import com.android.mail.providers.Attachment;
+import com.android.mail.providers.Message;
+import com.android.mail.providers.UIProvider;
+import com.android.mail.ui.AttachmentTile;
+import com.android.mail.ui.AttachmentTileGrid;
+import com.android.mail.utils.LogUtils;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
@@ -49,6 +52,8 @@
private static final String LOG_TAG = new LogUtils().getLogTag();
private ArrayList<Attachment> mAttachments;
private AttachmentDeletedListener mChangeListener;
+ private AttachmentTileGrid mTileGrid;
+ private LinearLayout mAttachmentLayout;
public AttachmentsView(Context context) {
this(context, null);
@@ -59,6 +64,14 @@
mAttachments = Lists.newArrayList();
}
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mTileGrid = (AttachmentTileGrid) findViewById(R.id.attachment_tile_grid);
+ mAttachmentLayout = (LinearLayout) findViewById(R.id.attachment_bar_list);
+ }
+
/**
* Set a listener for changes to the attachments.
* @param listener
@@ -77,27 +90,42 @@
}
mAttachments.add(attachment);
- final AttachmentComposeView attachmentView =
- new AttachmentComposeView(getContext(), attachment);
+ // If we have an attachment that should be shown in a tiled look,
+ // set up the tile and add it to the tile grid.
+ if (AttachmentTile.isTiledAttachment(attachment)) {
+ final ComposeAttachmentTile attachmentTile =
+ mTileGrid.addComposeTileFromAttachment(attachment);
+ attachmentTile.addDeleteListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ deleteAttachment(attachmentTile, attachment);
+ }
+ });
+ // Otherwise, use the old bar look and add it to the new
+ // inner LinearLayout.
+ } else {
+ final AttachmentComposeView attachmentView =
+ new AttachmentComposeView(getContext(), attachment);
- attachmentView.addDeleteListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- deleteAttachment(attachmentView, attachment);
- }
- });
+ attachmentView.addDeleteListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ deleteAttachment(attachmentView, attachment);
+ }
+ });
- addView(attachmentView, new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.MATCH_PARENT,
- LinearLayout.LayoutParams.MATCH_PARENT));
+ mAttachmentLayout.addView(attachmentView, new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT));
+ }
}
@VisibleForTesting
- protected void deleteAttachment(final AttachmentComposeView attachmentView,
+ protected void deleteAttachment(final View attachmentView,
final Attachment attachment) {
mAttachments.remove(attachment);
- removeView(attachmentView);
+ ((ViewGroup) attachmentView.getParent()).removeView(attachmentView);
if (mChangeListener != null) {
mChangeListener.onAttachmentDeleted();
}
@@ -119,7 +147,8 @@
*/
public void deleteAllAttachments() {
mAttachments.clear();
- removeAllViews();
+ mTileGrid.removeAllViews();
+ mAttachmentLayout.removeAllViews();
}
/**
diff --git a/src/com/android/mail/compose/ComposeAttachmentTile.java b/src/com/android/mail/compose/ComposeAttachmentTile.java
new file mode 100644
index 0000000..0ece410
--- /dev/null
+++ b/src/com/android/mail/compose/ComposeAttachmentTile.java
@@ -0,0 +1,39 @@
+package com.android.mail.compose;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+
+import com.android.mail.R;
+import com.android.mail.ui.AttachmentTile;
+
+public class ComposeAttachmentTile extends AttachmentTile implements AttachmentDeletionInterface {
+ private ImageButton mDeleteButton;
+
+ public ComposeAttachmentTile(Context context) {
+ this(context, null);
+ }
+
+ public ComposeAttachmentTile(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public static ComposeAttachmentTile inflate(LayoutInflater inflater, ViewGroup parent) {
+ ComposeAttachmentTile view = (ComposeAttachmentTile) inflater.inflate(
+ R.layout.compose_attachment_tile, parent, false);
+ return view;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mDeleteButton = (ImageButton) findViewById(R.id.attachment_tile_close_button);
+ }
+
+ public void addDeleteListener(OnClickListener clickListener) {
+ mDeleteButton.setOnClickListener(clickListener);
+ }
+}
diff --git a/src/com/android/mail/ui/AttachmentTile.java b/src/com/android/mail/ui/AttachmentTile.java
new file mode 100644
index 0000000..bfb9e83
--- /dev/null
+++ b/src/com/android/mail/ui/AttachmentTile.java
@@ -0,0 +1,174 @@
+package com.android.mail.ui;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+
+import com.android.mail.R;
+import com.android.mail.photo.util.ImageUtils;
+import com.android.mail.providers.Attachment;
+import com.android.mail.utils.LogUtils;
+
+import java.io.IOException;
+
+/**
+ * Base class for attachment tiles that handles the work
+ * of fetching and displaying the bitmaps for the tiles.
+ */
+public class AttachmentTile extends RelativeLayout {
+ protected Attachment mAttachment;
+ private ImageView mIcon;
+ private ImageView.ScaleType mIconScaleType;
+ private ThumbnailLoadTask mThumbnailTask;
+
+ private static final String LOG_TAG = new LogUtils().getLogTag();
+
+ /**
+ * Returns true if the attachment should be rendered as a tile.
+ * with a large image preview.
+ * @param attachment the attachment to render
+ * @return true if the attachment should be rendered as a tile
+ */
+ public static boolean isTiledAttachment(final Attachment attachment) {
+ return ImageUtils.isImageMimeType(attachment.contentType);
+ }
+
+ public AttachmentTile(Context context) {
+ this(context, null);
+ }
+
+ public AttachmentTile(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mIcon = (ImageView) findViewById(R.id.attachment_tile_image);
+ mIconScaleType = mIcon.getScaleType();
+ }
+
+ /**
+ * Render or update an attachment's view. This happens immediately upon instantiation, and
+ * repeatedly as status updates stream in, so only properties with new or changed values will
+ * cause sub-views to update.
+ *
+ */
+ public void render(Attachment attachment, Uri attachmentsListUri, int index) {
+ if (attachment == null) {
+ setVisibility(View.INVISIBLE);
+ return;
+ }
+
+ final Attachment prevAttachment = mAttachment;
+ mAttachment = attachment;
+
+ LogUtils.d(LOG_TAG, "got attachment list row: name=%s state/dest=%d/%d dled=%d" +
+ " contentUri=%s MIME=%s", attachment.name, attachment.state,
+ attachment.destination, attachment.downloadedSize, attachment.contentUri,
+ attachment.contentType);
+
+ setupThumbnailPreview(attachment, prevAttachment);
+ }
+
+ private void setupThumbnailPreview(Attachment attachment, final Attachment prevAttachment) {
+ final Uri imageUri = attachment.getImageUri();
+ final Uri prevImageUri = (prevAttachment == null) ? null : prevAttachment.getImageUri();
+ // begin loading a thumbnail if this is an image and either the thumbnail or the original
+ // content is ready (and different from any existing image)
+ if (imageUri != null && (prevImageUri == null || !imageUri.equals(prevImageUri))) {
+ // cancel/dispose any existing task and start a new one
+ if (mThumbnailTask != null) {
+ mThumbnailTask.cancel(true);
+ }
+ mThumbnailTask = new ThumbnailLoadTask(mIcon.getWidth(), mIcon.getHeight());
+ mThumbnailTask.execute(imageUri);
+ } else if (imageUri == null) {
+ // not an image, or no thumbnail exists. fall back to default.
+ // async image load must separately ensure the default appears upon load failure.
+ setThumbnailToDefault();
+ }
+ }
+
+ private void setThumbnailToDefault() {
+ mIcon.setImageResource(R.drawable.ic_menu_attachment_holo_light);
+ mIcon.setScaleType(ImageView.ScaleType.CENTER);
+ }
+
+ private class ThumbnailLoadTask extends AsyncTask<Uri, Void, Bitmap> {
+
+ private final int mWidth;
+ private final int mHeight;
+
+ public ThumbnailLoadTask(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ @Override
+ protected Bitmap doInBackground(Uri... params) {
+ final Uri thumbnailUri = params[0];
+
+ AssetFileDescriptor fd = null;
+ Bitmap result = null;
+
+ try {
+ fd = getContext().getContentResolver().openAssetFileDescriptor(thumbnailUri, "r");
+ if (isCancelled() || fd == null) {
+ return null;
+ }
+
+ final BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inJustDecodeBounds = true;
+
+ BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, opts);
+ if (isCancelled() || opts.outWidth == -1 || opts.outHeight == -1) {
+ return null;
+ }
+
+ opts.inJustDecodeBounds = false;
+
+ LogUtils.d(LOG_TAG, "in background, src w/h=%d/%d dst w/h=%d/%d, divider=%d",
+ opts.outWidth, opts.outHeight, mWidth, mHeight, opts.inSampleSize);
+
+ result = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor(), null, opts);
+
+ } catch (Throwable t) {
+ LogUtils.e(LOG_TAG, t, "Unable to decode thumbnail %s", thumbnailUri);
+ } finally {
+ if (fd != null) {
+ try {
+ fd.close();
+ } catch (IOException e) {
+ LogUtils.e(LOG_TAG, e, "");
+ }
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap result) {
+ if (result == null) {
+ LogUtils.d(LOG_TAG, "back in UI thread, decode failed");
+ setThumbnailToDefault();
+ return;
+ }
+
+ LogUtils.d(LOG_TAG, "back in UI thread, decode success, w/h=%d/%d", result.getWidth(),
+ result.getHeight());
+ mIcon.setImageBitmap(result);
+ mIcon.setScaleType(mIconScaleType);
+ }
+
+ }
+}
diff --git a/src/com/android/mail/browse/AttachmentTileGrid.java b/src/com/android/mail/ui/AttachmentTileGrid.java
similarity index 87%
rename from src/com/android/mail/browse/AttachmentTileGrid.java
rename to src/com/android/mail/ui/AttachmentTileGrid.java
index 84d483b..491d0e4 100644
--- a/src/com/android/mail/browse/AttachmentTileGrid.java
+++ b/src/com/android/mail/ui/AttachmentTileGrid.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.mail.browse;
+package com.android.mail.ui;
import android.content.Context;
import android.net.Uri;
@@ -24,12 +24,14 @@
import android.widget.FrameLayout;
import com.android.mail.R;
+import com.android.mail.browse.MessageAttachmentTile;
+import com.android.mail.compose.ComposeAttachmentTile;
import com.android.mail.providers.Attachment;
import java.util.List;
/**
- * Acts as a grid composed of {@link MessageAttachmentTile}s.
+ * Acts as a grid composed of {@link AttachmentTile}s.
*/
public class AttachmentTileGrid extends FrameLayout {
private LayoutInflater mInflater;
@@ -52,23 +54,33 @@
// Adding tiles to grid and filling in attachment information
int index = 0;
for (Attachment attachment : list) {
- addTileFromAttachment(attachment, index++);
+ addMessageTileFromAttachment(attachment, index++);
}
}
- private void addTileFromAttachment(Attachment attachment, int index) {
- final MessageAttachmentTile attachmentTile;
+ private void addMessageTileFromAttachment(Attachment attachment, int index) {
+ final AttachmentTile attachmentTile;
if (getChildCount() <= index) {
attachmentTile = MessageAttachmentTile.inflate(mInflater, this);
addView(attachmentTile);
} else {
- attachmentTile = (MessageAttachmentTile) getChildAt(index);
+ attachmentTile = (AttachmentTile) getChildAt(index);
}
attachmentTile.render(attachment, mAttachmentsListUri, index);
}
+ public ComposeAttachmentTile addComposeTileFromAttachment(Attachment attachment) {
+ final ComposeAttachmentTile attachmentTile =
+ ComposeAttachmentTile.inflate(mInflater, this);
+
+ addView(attachmentTile);
+ attachmentTile.render(attachment, null, -1);
+
+ return attachmentTile;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
onMeasureForTiles(widthMeasureSpec);