blob: 9c2850b88077ac74bf8654a267b645ee54f32fbd [file] [log] [blame]
/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 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.
*/
package com.android.mms.ui;
import com.android.mms.R;
import com.android.mms.util.ContactNameCache;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Handler;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.TextAppearanceSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* This class manages the view for given conversation.
*/
public class ConversationHeaderView extends RelativeLayout {
private static final String TAG = "ConversationHeaderView";
private static final boolean DEBUG = false;
private TextView mSubjectView;
private TextView mFromView;
private TextView mDateView;
private View mAttachmentView;
private View mUnreadIndicator;
private View mErrorIndicator;
// For posting UI update Runnables from other threads:
private Handler mHandler = new Handler();
// Access to mConversationHeader is guarded by mConversationHeaderLock.
private final Object mConversationHeaderLock = new Object();
private ConversationHeader mConversationHeader;
public ConversationHeaderView(Context context) {
super(context);
}
public ConversationHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mFromView = (TextView) findViewById(R.id.from);
mSubjectView = (TextView) findViewById(R.id.subject);
mDateView = (TextView) findViewById(R.id.date);
mAttachmentView = findViewById(R.id.attachment);
mUnreadIndicator = findViewById(R.id.unread_indicator);
mErrorIndicator = findViewById(R.id.error);
}
public ConversationHeader getConversationHeader() {
synchronized (mConversationHeaderLock) {
return mConversationHeader;
}
}
private void setConversationHeader(ConversationHeader header) {
synchronized (mConversationHeaderLock) {
mConversationHeader = header;
}
}
/**
* Only used for header binding.
*/
public void bind(String title, String explain) {
mFromView.setText(title);
mSubjectView.setText(explain);
}
private CharSequence formatMessage(ConversationHeader ch) {
final int size = android.R.style.TextAppearance_Small;
final int color = android.R.styleable.Theme_textColorSecondary;
String from = ch.getFrom();
if (from == null) {
// The temporary text users see while the names of contacts are loading.
// TODO: evaluate a better or prettier solution for this?
from = "...";
}
SpannableStringBuilder buf = new SpannableStringBuilder(from);
if (ch.getMessageCount() > 1) {
buf.append(" (" + ch.getMessageCount() + ") ");
}
int before = buf.length();
if (ch.hasDraft()) {
buf.append(" ");
buf.append(mContext.getResources().getString(R.string.has_draft));
buf.setSpan(new TextAppearanceSpan(mContext, size, color), before,
buf.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
buf.setSpan(new ForegroundColorSpan(
mContext.getResources().getColor(R.drawable.text_color_red)),
before, buf.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
return buf;
}
// Called by another thread that loaded an updated
// ConversationHeader for us. Note, however, that this view
// might've been re-used for a different header in the meantime,
// so we have to double-check that we still want this header.
public void onHeaderLoaded(final ConversationHeader newHeader) {
synchronized (mConversationHeaderLock) {
if (mConversationHeader != newHeader) {
// The user scrolled away before the item loaded and
// this view has been repurposed.
return;
}
// TODO: as an optimization, send a message to mHandler instead
// of posting a Runnable.
mHandler.post(new Runnable() {
public void run() {
synchronized (mConversationHeaderLock) {
if (mConversationHeader == newHeader) {
mFromView.setText(formatMessage(newHeader));
}
}
}
});
}
}
public final void bind(Context context, final ConversationHeader ch) {
if (DEBUG) Log.v(TAG, "bind()");
ConversationHeader oldHeader = getConversationHeader();
setConversationHeader(ch);
mAttachmentView.setVisibility(ch.hasAttachment() ? VISIBLE : INVISIBLE);
// Date
mDateView.setText(ch.getDate());
// From.
mFromView.setText(formatMessage(ch));
// The From above may be incomplete (still loading), so we register ourselves
// as a callback later to get woken up in onHeaderLoaded() when it changes.
if (ch.getFrom() == null) {
ch.setWaitingView(this);
}
boolean isRead = ch.isRead();
// Change font-face only if required.
if (oldHeader == null || oldHeader.isRead() != isRead) {
Typeface typeFace = isRead
? Typeface.DEFAULT
: Typeface.DEFAULT_BOLD;
mDateView.setTypeface(typeFace);
mFromView.setTypeface(typeFace);
}
mUnreadIndicator.setVisibility(isRead ? INVISIBLE : VISIBLE);
// Subject
mSubjectView.setText(ch.getSubject());
// Transmission error indicator.
mErrorIndicator.setVisibility(ch.hasError() ? VISIBLE : INVISIBLE);
}
}