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