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