MessageFooterView.java revision b8331b4565566ca733997398e8c07a26cd2bee98
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.LoaderManager; 21import android.content.Context; 22import android.content.Loader; 23import android.database.Cursor; 24import android.os.Bundle; 25import android.util.AttributeSet; 26import android.view.LayoutInflater; 27import android.view.View; 28import android.widget.LinearLayout; 29import android.widget.TextView; 30 31import com.android.mail.R; 32import com.android.mail.browse.AttachmentLoader.AttachmentCursor; 33import com.android.mail.browse.ConversationContainer.DetachListener; 34import com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem; 35import com.android.mail.providers.Attachment; 36import com.android.mail.providers.Message; 37import com.android.mail.ui.AttachmentTile; 38import com.android.mail.ui.AttachmentTileGrid; 39import com.android.mail.utils.LogTag; 40import com.android.mail.utils.LogUtils; 41import com.google.common.collect.Lists; 42 43import java.util.ArrayList; 44import java.util.List; 45 46public class MessageFooterView extends LinearLayout implements DetachListener, 47 LoaderManager.LoaderCallbacks<Cursor> { 48 49 private MessageHeaderItem mMessageHeaderItem; 50 private LoaderManager mLoaderManager; 51 private AttachmentCursor mAttachmentsCursor; 52 private TextView mTitleText; 53 private View mTitleBar; 54 private AttachmentTileGrid mAttachmentGrid; 55 private LinearLayout mAttachmentBarList; 56 57 private final LayoutInflater mInflater; 58 59 private static final String LOG_TAG = LogTag.getLogTag(); 60 61 public MessageFooterView(Context context) { 62 this(context, null); 63 } 64 65 public MessageFooterView(Context context, AttributeSet attrs) { 66 super(context, attrs); 67 68 mInflater = LayoutInflater.from(context); 69 } 70 71 @Override 72 protected void onFinishInflate() { 73 super.onFinishInflate(); 74 75 mTitleText = (TextView) findViewById(R.id.attachments_header_text); 76 mTitleBar = findViewById(R.id.attachments_header_bar); 77 mAttachmentGrid = (AttachmentTileGrid) findViewById(R.id.attachment_tile_grid); 78 mAttachmentBarList = (LinearLayout) findViewById(R.id.attachment_bar_list); 79 } 80 81 public void initialize(LoaderManager loaderManager) { 82 mLoaderManager = loaderManager; 83 } 84 85 public void bind(MessageHeaderItem headerItem, boolean measureOnly) { 86 // Resets the footer view. This step is only done if the 87 // attachmentsListUri changes so that we don't 88 // repeat the work of layout and measure when 89 // we're only updating the attachments. 90 if (mMessageHeaderItem != null && 91 mMessageHeaderItem.message != null && 92 mMessageHeaderItem.message.attachmentListUri != null && 93 !mMessageHeaderItem.message.attachmentListUri.equals( 94 headerItem.message.attachmentListUri)) { 95 mAttachmentGrid.removeAllViewsInLayout(); 96 mAttachmentBarList.removeAllViewsInLayout(); 97 mTitleText.setVisibility(View.GONE); 98 mTitleBar.setVisibility(View.GONE); 99 mAttachmentGrid.setVisibility(View.GONE); 100 mAttachmentBarList.setVisibility(View.GONE); 101 } 102 103 mMessageHeaderItem = headerItem; 104 105 // kick off load of Attachment objects in background thread 106 // but don't do any Loader work if we're only measuring 107 final Integer attachmentLoaderId = getAttachmentLoaderId(); 108 if (!measureOnly && attachmentLoaderId != null) { 109 LogUtils.i(LOG_TAG, "binding footer view, calling initLoader for message %d", 110 attachmentLoaderId); 111 mLoaderManager.initLoader(attachmentLoaderId, Bundle.EMPTY, this); 112 } 113 114 // Do an initial render if initLoader didn't already do one 115 if (mAttachmentGrid.getChildCount() == 0 && 116 mAttachmentBarList.getChildCount() == 0) { 117 renderAttachments(); 118 } 119 setVisibility(mMessageHeaderItem.isExpanded() ? VISIBLE : GONE); 120 } 121 122 private void unbind() { 123 final Integer loaderId = getAttachmentLoaderId(); 124 if (mLoaderManager != null && loaderId != null) { 125 LogUtils.i(LOG_TAG, "detaching footer view, calling destroyLoader for message %d", 126 loaderId); 127 mLoaderManager.destroyLoader(loaderId); 128 } 129 } 130 131 private void renderAttachments() { 132 final List<Attachment> attachments; 133 if (mAttachmentsCursor != null && !mAttachmentsCursor.isClosed()) { 134 int i = -1; 135 attachments = Lists.newArrayList(); 136 while (mAttachmentsCursor.moveToPosition(++i)) { 137 attachments.add(mAttachmentsCursor.get()); 138 } 139 } else { 140 // before the attachment loader results are in, we can still render immediately using 141 // the basic info in the message's attachmentsJSON 142 attachments = mMessageHeaderItem.message.getAttachments(); 143 } 144 renderAttachments(attachments); 145 } 146 147 private void renderAttachments(List<Attachment> attachments) { 148 if (attachments == null || attachments.isEmpty()) { 149 return; 150 } 151 152 // filter the attachments into tiled and non-tiled 153 final int maxSize = attachments.size(); 154 List<Attachment> tiledAttachments = new ArrayList<Attachment>(maxSize); 155 List<Attachment> barAttachments = new ArrayList<Attachment>(maxSize); 156 157 for (Attachment attachment : attachments) { 158 if (AttachmentTile.isTiledAttachment(attachment)) { 159 tiledAttachments.add(attachment); 160 } else { 161 barAttachments.add(attachment); 162 } 163 } 164 165 mTitleText.setVisibility(View.VISIBLE); 166 mTitleBar.setVisibility(View.VISIBLE); 167 168 renderTiledAttachments(tiledAttachments); 169 renderBarAttachments(barAttachments); 170 } 171 172 private void renderTiledAttachments(List<Attachment> tiledAttachments) { 173 mAttachmentGrid.setVisibility(View.VISIBLE); 174 175 // Setup the tiles. 176 mAttachmentGrid.configureGrid( 177 mMessageHeaderItem.message.attachmentListUri, tiledAttachments); 178 } 179 180 private void renderBarAttachments(List<Attachment> barAttachments) { 181 mAttachmentBarList.setVisibility(View.VISIBLE); 182 183 for (Attachment attachment : barAttachments) { 184 MessageAttachmentBar barAttachmentView = 185 (MessageAttachmentBar) mAttachmentBarList.findViewWithTag(attachment.uri); 186 187 if (barAttachmentView == null) { 188 barAttachmentView = MessageAttachmentBar.inflate(mInflater, this); 189 barAttachmentView.setTag(attachment.uri); 190 mAttachmentBarList.addView(barAttachmentView); 191 } 192 193 barAttachmentView.render(attachment); 194 } 195 } 196 197 private Integer getAttachmentLoaderId() { 198 Integer id = null; 199 final Message msg = mMessageHeaderItem == null ? null : mMessageHeaderItem.message; 200 if (msg != null && msg.hasAttachments && msg.attachmentListUri != null) { 201 id = msg.attachmentListUri.hashCode(); 202 } 203 return id; 204 } 205 206 @Override 207 protected void onDetachedFromWindow() { 208 super.onDetachedFromWindow(); 209 unbind(); 210 } 211 212 @Override 213 public void onDetachedFromParent() { 214 unbind(); 215 } 216 217 @Override 218 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 219 return new AttachmentLoader(getContext(), mMessageHeaderItem.message.attachmentListUri); 220 } 221 222 @Override 223 public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 224 mAttachmentsCursor = (AttachmentCursor) data; 225 226 if (mAttachmentsCursor == null || mAttachmentsCursor.isClosed()) { 227 return; 228 } 229 230 renderAttachments(); 231 } 232 233 @Override 234 public void onLoaderReset(Loader<Cursor> loader) { 235 mAttachmentsCursor = null; 236 } 237} 238