blob: 671778d03ad8714de88ef72ff429cbcb630bd972 [file] [log] [blame]
Andy Huang7bdc3752012-03-25 17:18:19 -07001/*
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
Paul Westbrook8081df42012-09-10 15:43:36 -070020import android.app.FragmentManager;
Andy Huang7bdc3752012-03-25 17:18:19 -070021import android.app.LoaderManager;
22import android.content.Context;
Andy Huangadbf3e82012-10-13 13:30:19 -070023import android.view.Gravity;
Andy Huang7bdc3752012-03-25 17:18:19 -070024import android.view.LayoutInflater;
25import android.view.View;
26import android.view.ViewGroup;
Andy Huang7bdc3752012-03-25 17:18:19 -070027import android.widget.BaseAdapter;
Andy Huang7bdc3752012-03-25 17:18:19 -070028
Andy Huangb8331b42012-07-16 19:08:53 -070029import com.android.mail.ContactInfoSource;
Andy Huang7bdc3752012-03-25 17:18:19 -070030import com.android.mail.FormattedDateBuilder;
31import com.android.mail.R;
32import com.android.mail.browse.ConversationViewHeader.ConversationViewHeaderCallbacks;
33import com.android.mail.browse.MessageHeaderView.MessageHeaderViewCallbacks;
Andy Huang46dfba62012-04-19 01:47:32 -070034import com.android.mail.browse.SuperCollapsedBlock.OnClickListener;
Andy Huang65fe28f2012-04-06 18:08:53 -070035import com.android.mail.providers.Address;
Andy Huang7bdc3752012-03-25 17:18:19 -070036import com.android.mail.providers.Conversation;
Andy Huang7bdc3752012-03-25 17:18:19 -070037import com.android.mail.providers.UIProvider;
Paul Westbrook8081df42012-09-10 15:43:36 -070038import com.android.mail.ui.ControllableActivity;
Vikram Aggarwal69a6cdf2013-01-08 16:05:17 -080039import com.android.mail.utils.VeiledAddressMatcher;
Andy Huang014ea4c2012-09-25 14:50:54 -070040import com.google.common.base.Objects;
Andy Huangc7543572012-04-03 15:34:29 -070041import com.google.common.collect.Lists;
Andy Huang7bdc3752012-03-25 17:18:19 -070042
Andy Huang46dfba62012-04-19 01:47:32 -070043import java.util.Collection;
Andy Huang7bdc3752012-03-25 17:18:19 -070044import java.util.List;
Andy Huang65fe28f2012-04-06 18:08:53 -070045import java.util.Map;
Andy Huang7bdc3752012-03-25 17:18:19 -070046
47/**
48 * A specialized adapter that contains overlay views to draw on top of the underlying conversation
49 * WebView. Each independently drawn overlay view gets its own item in this adapter, and indices
50 * in this adapter do not necessarily line up with cursor indices. For example, an expanded
51 * message may have a header and footer, and since they are not drawn coupled together, they each
52 * get an adapter item.
53 * <p>
Andy Huang46dfba62012-04-19 01:47:32 -070054 * Each item in this adapter is a {@link ConversationOverlayItem} to expose enough information
55 * to {@link ConversationContainer} so that it can position overlays properly.
Andy Huang7bdc3752012-03-25 17:18:19 -070056 *
57 */
58public class ConversationViewAdapter extends BaseAdapter {
59
60 private Context mContext;
61 private final FormattedDateBuilder mDateBuilder;
Andy Huang28b7aee2012-08-20 20:27:32 -070062 private final ConversationAccountController mAccountController;
Andy Huang7bdc3752012-03-25 17:18:19 -070063 private final LoaderManager mLoaderManager;
Paul Westbrook8081df42012-09-10 15:43:36 -070064 private final FragmentManager mFragmentManager;
Andy Huang7bdc3752012-03-25 17:18:19 -070065 private final MessageHeaderViewCallbacks mMessageCallbacks;
Andy Huangb8331b42012-07-16 19:08:53 -070066 private final ContactInfoSource mContactInfoSource;
Andy Huang7bdc3752012-03-25 17:18:19 -070067 private ConversationViewHeaderCallbacks mConversationCallbacks;
Andy Huang46dfba62012-04-19 01:47:32 -070068 private OnClickListener mSuperCollapsedListener;
Andy Huang65fe28f2012-04-06 18:08:53 -070069 private Map<String, Address> mAddressCache;
Andy Huang7bdc3752012-03-25 17:18:19 -070070 private final LayoutInflater mInflater;
71
Andy Huang46dfba62012-04-19 01:47:32 -070072 private final List<ConversationOverlayItem> mItems;
Vikram Aggarwal69a6cdf2013-01-08 16:05:17 -080073 private final VeiledAddressMatcher mMatcher;
Andy Huang7bdc3752012-03-25 17:18:19 -070074
75 public static final int VIEW_TYPE_CONVERSATION_HEADER = 0;
Andrew Sapperstein9f957f32013-07-19 15:18:18 -070076 public static final int VIEW_TYPE_AD_HEADER = 1;
Andrew Sapperstein606dbd72013-07-30 19:14:23 -070077 public static final int VIEW_TYPE_MESSAGE_HEADER = 2;
78 public static final int VIEW_TYPE_MESSAGE_FOOTER = 3;
79 public static final int VIEW_TYPE_SUPER_COLLAPSED_BLOCK = 4;
80 public static final int VIEW_TYPE_BORDER = 5;
81 public static final int VIEW_TYPE_COUNT = 6;
Andy Huang7bdc3752012-03-25 17:18:19 -070082
Andy Huang46dfba62012-04-19 01:47:32 -070083 public class ConversationHeaderItem extends ConversationOverlayItem {
Andy Huang7bdc3752012-03-25 17:18:19 -070084 public final Conversation mConversation;
85
86 private ConversationHeaderItem(Conversation conv) {
87 mConversation = conv;
88 }
89
90 @Override
91 public int getType() {
92 return VIEW_TYPE_CONVERSATION_HEADER;
93 }
94
95 @Override
96 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
97 final ConversationViewHeader headerView = (ConversationViewHeader) inflater.inflate(
98 R.layout.conversation_view_header, parent, false);
Andy Huang28b7aee2012-08-20 20:27:32 -070099 headerView.setCallbacks(mConversationCallbacks, mAccountController);
Mark Weiab2d9982012-09-25 13:06:17 -0700100 headerView.bind(this);
Andy Huang7388dba2012-09-25 18:30:28 -0700101 headerView.setSubject(mConversation.subject);
Andy Huang28b7aee2012-08-20 20:27:32 -0700102 if (mAccountController.getAccount().supportsCapability(
Andy Huang7bdc3752012-03-25 17:18:19 -0700103 UIProvider.AccountCapabilities.MULTIPLE_FOLDERS_PER_CONV)) {
Andy Huang7388dba2012-09-25 18:30:28 -0700104 headerView.setFolders(mConversation);
Andy Huang7bdc3752012-03-25 17:18:19 -0700105 }
106
107 return headerView;
108 }
109
110 @Override
Andy Huangb8331b42012-07-16 19:08:53 -0700111 public void bindView(View v, boolean measureOnly) {
Mark Weiab2d9982012-09-25 13:06:17 -0700112 ConversationViewHeader header = (ConversationViewHeader) v;
113 header.bind(this);
Andy Huang7bdc3752012-03-25 17:18:19 -0700114 }
115
116 @Override
Andy Huang7bdc3752012-03-25 17:18:19 -0700117 public boolean isContiguous() {
118 return true;
119 }
120
121 }
122
Andrew Sapperstein4ddda2f2013-06-10 11:15:38 -0700123 public static class MessageHeaderItem extends ConversationOverlayItem {
124
125 private final ConversationViewAdapter mAdapter;
126
Andy Huang014ea4c2012-09-25 14:50:54 -0700127 private ConversationMessage mMessage;
Andy Huang65fe28f2012-04-06 18:08:53 -0700128
129 // view state variables
Andy Huangc7543572012-04-03 15:34:29 -0700130 private boolean mExpanded;
131 public boolean detailsExpanded;
Scott Kennedy20273842012-11-07 11:16:21 -0800132 private boolean mShowImages;
Andy Huang7bdc3752012-03-25 17:18:19 -0700133
Andy Huang65fe28f2012-04-06 18:08:53 -0700134 // cached values to speed up re-rendering during view recycling
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700135 private CharSequence mTimestampShort;
136 private CharSequence mTimestampLong;
137 private long mTimestampMs;
138 private FormattedDateBuilder mDateBuilder;
Andy Huang65fe28f2012-04-06 18:08:53 -0700139 public CharSequence recipientSummaryText;
140
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700141 MessageHeaderItem(ConversationViewAdapter adapter, FormattedDateBuilder dateBuilder,
142 ConversationMessage message, boolean expanded, boolean showImages) {
Andrew Sapperstein4ddda2f2013-06-10 11:15:38 -0700143 mAdapter = adapter;
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700144 mDateBuilder = dateBuilder;
Andy Huang014ea4c2012-09-25 14:50:54 -0700145 mMessage = message;
Andy Huangc7543572012-04-03 15:34:29 -0700146 mExpanded = expanded;
Scott Kennedy20273842012-11-07 11:16:21 -0800147 mShowImages = showImages;
Andy Huangc7543572012-04-03 15:34:29 -0700148
149 detailsExpanded = false;
Andy Huang7bdc3752012-03-25 17:18:19 -0700150 }
151
Andy Huang014ea4c2012-09-25 14:50:54 -0700152 public ConversationMessage getMessage() {
153 return mMessage;
154 }
155
Andy Huang7bdc3752012-03-25 17:18:19 -0700156 @Override
157 public int getType() {
158 return VIEW_TYPE_MESSAGE_HEADER;
159 }
160
161 @Override
162 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
163 final MessageHeaderView v = (MessageHeaderView) inflater.inflate(
164 R.layout.conversation_message_header, parent, false);
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700165 v.initialize(mAdapter.mAccountController,
Andrew Sapperstein4ddda2f2013-06-10 11:15:38 -0700166 mAdapter.mAddressCache);
167 v.setCallbacks(mAdapter.mMessageCallbacks);
168 v.setContactInfoSource(mAdapter.mContactInfoSource);
169 v.setVeiledMatcher(mAdapter.mMatcher);
Andy Huang7bdc3752012-03-25 17:18:19 -0700170 return v;
171 }
172
173 @Override
Andy Huangb8331b42012-07-16 19:08:53 -0700174 public void bindView(View v, boolean measureOnly) {
Andy Huang7bdc3752012-03-25 17:18:19 -0700175 final MessageHeaderView header = (MessageHeaderView) v;
Andy Huang28b7aee2012-08-20 20:27:32 -0700176 header.bind(this, measureOnly);
Andy Huang7bdc3752012-03-25 17:18:19 -0700177 }
178
179 @Override
Andy Huang6b3d0d92012-10-30 15:46:48 -0700180 public void onModelUpdated(View v) {
181 final MessageHeaderView header = (MessageHeaderView) v;
182 header.refresh();
183 }
184
185 @Override
Andy Huang7bdc3752012-03-25 17:18:19 -0700186 public boolean isContiguous() {
Andy Huangc7543572012-04-03 15:34:29 -0700187 return !isExpanded();
188 }
189
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700190 @Override
Andy Huangc7543572012-04-03 15:34:29 -0700191 public boolean isExpanded() {
192 return mExpanded;
193 }
194
195 public void setExpanded(boolean expanded) {
196 if (mExpanded != expanded) {
197 mExpanded = expanded;
198 }
Andy Huang7bdc3752012-03-25 17:18:19 -0700199 }
Andy Huang59e0b182012-08-14 14:32:23 -0700200
Scott Kennedy20273842012-11-07 11:16:21 -0800201 public boolean getShowImages() {
202 return mShowImages;
203 }
204
205 public void setShowImages(boolean showImages) {
206 mShowImages = showImages;
207 }
208
Andy Huang59e0b182012-08-14 14:32:23 -0700209 @Override
210 public boolean canBecomeSnapHeader() {
211 return isExpanded();
212 }
213
214 @Override
215 public boolean canPushSnapHeader() {
216 return true;
217 }
218
Andy Huang014ea4c2012-09-25 14:50:54 -0700219 @Override
220 public boolean belongsToMessage(ConversationMessage message) {
221 return Objects.equal(mMessage, message);
222 }
223
224 @Override
225 public void setMessage(ConversationMessage message) {
226 mMessage = message;
227 }
228
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700229 public CharSequence getTimestampShort() {
230 ensureTimestamps();
231 return mTimestampShort;
232 }
233
234 public CharSequence getTimestampLong() {
235 ensureTimestamps();
236 return mTimestampLong;
237 }
238
239 private void ensureTimestamps() {
240 if (mMessage.dateReceivedMs != mTimestampMs) {
241 mTimestampMs = mMessage.dateReceivedMs;
242 mTimestampShort = mDateBuilder.formatShortDate(mTimestampMs);
243 mTimestampLong = mDateBuilder.formatLongDateTime(mTimestampMs);
244 }
245 }
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700246
247 public ConversationViewAdapter getAdapter() {
248 return mAdapter;
249 }
Andy Huang7bdc3752012-03-25 17:18:19 -0700250 }
251
Andy Huang46dfba62012-04-19 01:47:32 -0700252 public class MessageFooterItem extends ConversationOverlayItem {
Andy Huang7bdc3752012-03-25 17:18:19 -0700253 /**
254 * A footer can only exist if there is a matching header. Requiring a header allows a
255 * footer to stay in sync with the expanded state of the header.
256 */
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700257 private final MessageHeaderItem mHeaderitem;
Andy Huang7bdc3752012-03-25 17:18:19 -0700258
259 private MessageFooterItem(MessageHeaderItem item) {
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700260 mHeaderitem = item;
Andy Huang7bdc3752012-03-25 17:18:19 -0700261 }
262
263 @Override
264 public int getType() {
265 return VIEW_TYPE_MESSAGE_FOOTER;
266 }
267
268 @Override
269 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
Andy Huangf0e95c32012-04-02 18:11:17 -0700270 final MessageFooterView v = (MessageFooterView) inflater.inflate(
271 R.layout.conversation_message_footer, parent, false);
Paul Westbrook8081df42012-09-10 15:43:36 -0700272 v.initialize(mLoaderManager, mFragmentManager);
Andy Huangf0e95c32012-04-02 18:11:17 -0700273 return v;
Andy Huang7bdc3752012-03-25 17:18:19 -0700274 }
275
276 @Override
Andy Huangb8331b42012-07-16 19:08:53 -0700277 public void bindView(View v, boolean measureOnly) {
Andy Huangf0e95c32012-04-02 18:11:17 -0700278 final MessageFooterView attachmentsView = (MessageFooterView) v;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700279 attachmentsView.bind(mHeaderitem, mAccountController.getAccount().uri, measureOnly);
Andy Huang7bdc3752012-03-25 17:18:19 -0700280 }
281
282 @Override
283 public boolean isContiguous() {
284 return true;
285 }
Andy Huangc7543572012-04-03 15:34:29 -0700286
287 @Override
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700288 public boolean isExpanded() {
289 return mHeaderitem.isExpanded();
290 }
291
292 @Override
Andy Huangadbf3e82012-10-13 13:30:19 -0700293 public int getGravity() {
294 // attachments are top-aligned within their spacer area
295 // Attachments should stay near the body they belong to, even when zoomed far in.
296 return Gravity.TOP;
297 }
298
299 @Override
Andy Huangc7543572012-04-03 15:34:29 -0700300 public int getHeight() {
301 // a footer may change height while its view does not exist because it is offscreen
302 // (but the header is onscreen and thus collapsible)
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700303 if (!mHeaderitem.isExpanded()) {
Andy Huangc7543572012-04-03 15:34:29 -0700304 return 0;
305 }
306 return super.getHeight();
307 }
Andy Huang7bdc3752012-03-25 17:18:19 -0700308 }
309
Andy Huang46dfba62012-04-19 01:47:32 -0700310 public class SuperCollapsedBlockItem extends ConversationOverlayItem {
311
312 private final int mStart;
313 private int mEnd;
314
315 private SuperCollapsedBlockItem(int start, int end) {
316 mStart = start;
317 mEnd = end;
318 }
319
320 @Override
321 public int getType() {
322 return VIEW_TYPE_SUPER_COLLAPSED_BLOCK;
323 }
324
325 @Override
326 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
327 final SuperCollapsedBlock scb = (SuperCollapsedBlock) inflater.inflate(
328 R.layout.super_collapsed_block, parent, false);
329 scb.initialize(mSuperCollapsedListener);
330 return scb;
331 }
332
333 @Override
Andy Huangb8331b42012-07-16 19:08:53 -0700334 public void bindView(View v, boolean measureOnly) {
Andy Huang46dfba62012-04-19 01:47:32 -0700335 final SuperCollapsedBlock scb = (SuperCollapsedBlock) v;
336 scb.bind(this);
337 }
338
339 @Override
340 public boolean isContiguous() {
341 return true;
342 }
343
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700344 @Override
345 public boolean isExpanded() {
346 return false;
347 }
348
Andy Huang46dfba62012-04-19 01:47:32 -0700349 public int getStart() {
350 return mStart;
351 }
352
353 public int getEnd() {
354 return mEnd;
355 }
Andy Huang59e0b182012-08-14 14:32:23 -0700356
357 @Override
358 public boolean canPushSnapHeader() {
359 return true;
360 }
Andy Huang46dfba62012-04-19 01:47:32 -0700361 }
362
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700363
364 public class BorderItem extends ConversationOverlayItem {
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700365 private final boolean mContiguous;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700366 private boolean mExpanded;
Andrew Sappersteine5398802013-07-29 20:55:38 -0700367 private final boolean mFirstBorder;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700368 private boolean mLastBorder;
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700369
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700370 public BorderItem(boolean contiguous, boolean isExpanded,
371 boolean firstBorder, boolean lastBorder) {
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700372 mContiguous = contiguous;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700373 mExpanded = isExpanded;
Andrew Sappersteine5398802013-07-29 20:55:38 -0700374 mFirstBorder = firstBorder;
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700375 mLastBorder = lastBorder;
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700376 }
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700377
378 @Override
379 public int getType() {
380 return VIEW_TYPE_BORDER;
381 }
382
383 @Override
384 public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
385 return inflater.inflate(R.layout.card_border, parent, false);
386 }
387
388 @Override
389 public void bindView(View v, boolean measureOnly) {
Andrew Sappersteine5398802013-07-29 20:55:38 -0700390 final BorderView border = (BorderView) v;
391 border.bind(this, measureOnly);
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700392 }
393
394 @Override
395 public boolean isContiguous() {
Andrew Sapperstein12c03aa2013-07-25 17:15:22 -0700396 return mContiguous;
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700397 }
398
399 @Override
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700400 public boolean isExpanded() {
401 return mExpanded;
402 }
403
404 public void setExpanded(boolean isExpanded) {
405 mExpanded = isExpanded;
406 }
407
408 @Override
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700409 public boolean canPushSnapHeader() {
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700410 return false;
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700411 }
Andrew Sappersteine5398802013-07-29 20:55:38 -0700412
413 public boolean isFirstBorder() {
414 return mFirstBorder;
415 }
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700416
417 public boolean isLastBorder() {
418 return mLastBorder;
419 }
420
421 public void setIsLastBorder(boolean isLastBorder) {
422 mLastBorder = isLastBorder;
423 }
424
425 public ConversationViewAdapter getAdapter() {
426 return ConversationViewAdapter.this;
427 }
428
429 @Override
430 public void rebindView(View view) {
431 bindView(view, false);
432 }
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700433 }
434
Paul Westbrook8081df42012-09-10 15:43:36 -0700435 public ConversationViewAdapter(ControllableActivity controllableActivity,
Andy Huang28b7aee2012-08-20 20:27:32 -0700436 ConversationAccountController accountController,
437 LoaderManager loaderManager,
Andy Huang7bdc3752012-03-25 17:18:19 -0700438 MessageHeaderViewCallbacks messageCallbacks,
Andy Huangb8331b42012-07-16 19:08:53 -0700439 ContactInfoSource contactInfoSource,
Andy Huang46dfba62012-04-19 01:47:32 -0700440 ConversationViewHeaderCallbacks convCallbacks,
Andy Huang59e0b182012-08-14 14:32:23 -0700441 SuperCollapsedBlock.OnClickListener scbListener, Map<String, Address> addressCache,
442 FormattedDateBuilder dateBuilder) {
Paul Westbrook8081df42012-09-10 15:43:36 -0700443 mContext = controllableActivity.getActivityContext();
Andy Huang59e0b182012-08-14 14:32:23 -0700444 mDateBuilder = dateBuilder;
Andy Huang28b7aee2012-08-20 20:27:32 -0700445 mAccountController = accountController;
Andy Huang7bdc3752012-03-25 17:18:19 -0700446 mLoaderManager = loaderManager;
Paul Westbrook8081df42012-09-10 15:43:36 -0700447 mFragmentManager = controllableActivity.getFragmentManager();
Andy Huang7bdc3752012-03-25 17:18:19 -0700448 mMessageCallbacks = messageCallbacks;
Andy Huangb8331b42012-07-16 19:08:53 -0700449 mContactInfoSource = contactInfoSource;
Andy Huang7bdc3752012-03-25 17:18:19 -0700450 mConversationCallbacks = convCallbacks;
Andy Huang46dfba62012-04-19 01:47:32 -0700451 mSuperCollapsedListener = scbListener;
Andy Huang65fe28f2012-04-06 18:08:53 -0700452 mAddressCache = addressCache;
Paul Westbrook8081df42012-09-10 15:43:36 -0700453 mInflater = LayoutInflater.from(mContext);
Andy Huang7bdc3752012-03-25 17:18:19 -0700454
455 mItems = Lists.newArrayList();
Vikram Aggarwal69a6cdf2013-01-08 16:05:17 -0800456 mMatcher = controllableActivity.getAccountController().getVeiledAddressMatcher();
Andy Huang7bdc3752012-03-25 17:18:19 -0700457 }
458
459 @Override
460 public int getCount() {
461 return mItems.size();
462 }
463
464 @Override
465 public int getItemViewType(int position) {
466 return mItems.get(position).getType();
467 }
468
469 @Override
470 public int getViewTypeCount() {
471 return VIEW_TYPE_COUNT;
472 }
473
474 @Override
Andy Huang46dfba62012-04-19 01:47:32 -0700475 public ConversationOverlayItem getItem(int position) {
Andy Huang7bdc3752012-03-25 17:18:19 -0700476 return mItems.get(position);
477 }
478
479 @Override
480 public long getItemId(int position) {
481 return position; // TODO: ensure this works well enough
482 }
483
484 @Override
485 public View getView(int position, View convertView, ViewGroup parent) {
Andy Huangb8331b42012-07-16 19:08:53 -0700486 return getView(getItem(position), convertView, parent, false /* measureOnly */);
Andy Huang46dfba62012-04-19 01:47:32 -0700487 }
488
Andy Huangb8331b42012-07-16 19:08:53 -0700489 public View getView(ConversationOverlayItem item, View convertView, ViewGroup parent,
490 boolean measureOnly) {
Andy Huang7bdc3752012-03-25 17:18:19 -0700491 final View v;
Andy Huang7bdc3752012-03-25 17:18:19 -0700492
493 if (convertView == null) {
494 v = item.createView(mContext, mInflater, parent);
495 } else {
496 v = convertView;
497 }
Andy Huangb8331b42012-07-16 19:08:53 -0700498 item.bindView(v, measureOnly);
Andy Huang7bdc3752012-03-25 17:18:19 -0700499
500 return v;
501 }
502
Andrew Sapperstein888388c2013-08-01 22:51:37 -0700503 public LayoutInflater getLayoutInflater() {
504 return mInflater;
505 }
506
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700507 public FormattedDateBuilder getDateBuilder() {
508 return mDateBuilder;
509 }
510
Andy Huang46dfba62012-04-19 01:47:32 -0700511 public int addItem(ConversationOverlayItem item) {
Andy Huang7bdc3752012-03-25 17:18:19 -0700512 final int pos = mItems.size();
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700513 item.setPosition(pos);
Andy Huang7bdc3752012-03-25 17:18:19 -0700514 mItems.add(item);
Andy Huang7bdc3752012-03-25 17:18:19 -0700515 return pos;
516 }
517
518 public void clear() {
519 mItems.clear();
Andy Huang6cb004b2012-10-26 15:37:32 -0700520 notifyDataSetChanged();
Andy Huang7bdc3752012-03-25 17:18:19 -0700521 }
522
523 public int addConversationHeader(Conversation conv) {
524 return addItem(new ConversationHeaderItem(conv));
525 }
526
Scott Kennedy20273842012-11-07 11:16:21 -0800527 public int addMessageHeader(ConversationMessage msg, boolean expanded, boolean showImages) {
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700528 return addItem(new MessageHeaderItem(this, mDateBuilder, msg, expanded, showImages));
Andy Huang7bdc3752012-03-25 17:18:19 -0700529 }
530
531 public int addMessageFooter(MessageHeaderItem headerItem) {
532 return addItem(new MessageFooterItem(headerItem));
533 }
534
Andrew Sapperstein4ddda2f2013-06-10 11:15:38 -0700535 public static MessageHeaderItem newMessageHeaderItem(ConversationViewAdapter adapter,
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700536 FormattedDateBuilder dateBuilder, ConversationMessage message,
537 boolean expanded, boolean showImages) {
538 return new MessageHeaderItem(adapter, dateBuilder, message, expanded, showImages);
Andy Huang46dfba62012-04-19 01:47:32 -0700539 }
540
541 public MessageFooterItem newMessageFooterItem(MessageHeaderItem headerItem) {
542 return new MessageFooterItem(headerItem);
543 }
544
545 public int addSuperCollapsedBlock(int start, int end) {
546 return addItem(new SuperCollapsedBlockItem(start, end));
547 }
548
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700549 public int addBorder(
550 boolean contiguous, boolean expanded, boolean firstBorder, boolean lastBorder) {
551 return addItem(new BorderItem(contiguous, expanded, firstBorder, lastBorder));
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700552 }
553
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700554 public BorderItem newBorderItem(boolean contiguous, boolean expanded) {
555 return new BorderItem(
556 contiguous, expanded, false /* firstBorder */, false /* lastBorder */);
Andrew Sapperstein14f93742013-07-25 14:29:56 -0700557 }
558
Andy Huang46dfba62012-04-19 01:47:32 -0700559 public void replaceSuperCollapsedBlock(SuperCollapsedBlockItem blockToRemove,
560 Collection<ConversationOverlayItem> replacements) {
561 final int pos = mItems.indexOf(blockToRemove);
562 if (pos == -1) {
563 return;
564 }
565
566 mItems.remove(pos);
567 mItems.addAll(pos, replacements);
Andrew Sappersteincee3c902013-07-31 10:52:02 -0700568
569 // update position for all items
570 for (int i = 0, size = mItems.size(); i < size; i++) {
571 mItems.get(i).setPosition(i);
572 }
Andy Huang46dfba62012-04-19 01:47:32 -0700573 }
574
Andy Huang6b3d0d92012-10-30 15:46:48 -0700575 public void updateItemsForMessage(ConversationMessage message,
576 List<Integer> affectedPositions) {
577 for (int i = 0, len = mItems.size(); i < len; i++) {
578 final ConversationOverlayItem item = mItems.get(i);
Andy Huang014ea4c2012-09-25 14:50:54 -0700579 if (item.belongsToMessage(message)) {
580 item.setMessage(message);
Andy Huang6b3d0d92012-10-30 15:46:48 -0700581 affectedPositions.add(i);
Andy Huang014ea4c2012-09-25 14:50:54 -0700582 }
583 }
Andy Huang014ea4c2012-09-25 14:50:54 -0700584 }
Andy Huang7bdc3752012-03-25 17:18:19 -0700585}