| /* |
| * 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 android.content.Context; |
| import android.graphics.Typeface; |
| import android.graphics.drawable.Drawable; |
| import android.os.Handler; |
| import android.text.Spannable; |
| import android.text.SpannableStringBuilder; |
| import android.text.style.ForegroundColorSpan; |
| import android.text.style.StyleSpan; |
| import android.text.style.TextAppearanceSpan; |
| import android.util.AttributeSet; |
| import android.util.Log; |
| import android.view.View; |
| import android.widget.Checkable; |
| import android.widget.QuickContactBadge; |
| import android.widget.RelativeLayout; |
| import android.widget.TextView; |
| |
| import com.android.mms.LogTag; |
| import com.android.mms.R; |
| import com.android.mms.data.Contact; |
| import com.android.mms.data.ContactList; |
| import com.android.mms.data.Conversation; |
| import com.android.mms.util.SmileyParser; |
| |
| /** |
| * This class manages the view for given conversation. |
| */ |
| public class ConversationListItem extends RelativeLayout implements Contact.UpdateListener, |
| Checkable { |
| private static final String TAG = "ConversationListItem"; |
| private static final boolean DEBUG = false; |
| |
| private TextView mSubjectView; |
| private TextView mFromView; |
| private TextView mDateView; |
| private View mAttachmentView; |
| private View mErrorIndicator; |
| private QuickContactBadge mAvatarView; |
| |
| static private Drawable sDefaultContactImage; |
| |
| // For posting UI update Runnables from other threads: |
| private Handler mHandler = new Handler(); |
| |
| private Conversation mConversation; |
| |
| public static final StyleSpan STYLE_BOLD = new StyleSpan(Typeface.BOLD); |
| |
| public ConversationListItem(Context context) { |
| super(context); |
| } |
| |
| public ConversationListItem(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| |
| if (sDefaultContactImage == null) { |
| sDefaultContactImage = context.getResources().getDrawable(R.drawable.ic_contact_picture); |
| } |
| } |
| |
| @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); |
| mErrorIndicator = findViewById(R.id.error); |
| mAvatarView = (QuickContactBadge) findViewById(R.id.avatar); |
| } |
| |
| public Conversation getConversation() { |
| return mConversation; |
| } |
| |
| /** |
| * Only used for header binding. |
| */ |
| public void bind(String title, String explain) { |
| mFromView.setText(title); |
| mSubjectView.setText(explain); |
| } |
| |
| private CharSequence formatMessage() { |
| final int color = android.R.styleable.Theme_textColorSecondary; |
| String from = mConversation.getRecipients().formatNames(", "); |
| |
| SpannableStringBuilder buf = new SpannableStringBuilder(from); |
| |
| if (mConversation.getMessageCount() > 1) { |
| int before = buf.length(); |
| buf.append(mContext.getResources().getString(R.string.message_count_format, |
| mConversation.getMessageCount())); |
| buf.setSpan(new ForegroundColorSpan( |
| mContext.getResources().getColor(R.color.message_count_color)), |
| before, buf.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); |
| } |
| if (mConversation.hasDraft()) { |
| buf.append(mContext.getResources().getString(R.string.draft_separator)); |
| int before = buf.length(); |
| int size; |
| buf.append(mContext.getResources().getString(R.string.has_draft)); |
| size = android.R.style.TextAppearance_Small; |
| 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); |
| } |
| |
| // Unread messages are shown in bold |
| if (mConversation.hasUnreadMessages()) { |
| buf.setSpan(STYLE_BOLD, 0, buf.length(), |
| Spannable.SPAN_INCLUSIVE_EXCLUSIVE); |
| } |
| return buf; |
| } |
| |
| private void updateAvatarView() { |
| Drawable avatarDrawable; |
| if (mConversation.getRecipients().size() == 1) { |
| Contact contact = mConversation.getRecipients().get(0); |
| avatarDrawable = contact.getAvatar(mContext, sDefaultContactImage); |
| |
| if (contact.existsInDatabase()) { |
| mAvatarView.assignContactUri(contact.getUri()); |
| } else { |
| mAvatarView.assignContactFromPhone(contact.getNumber(), true); |
| } |
| } else { |
| // TODO get a multiple recipients asset (or do something else) |
| avatarDrawable = sDefaultContactImage; |
| mAvatarView.assignContactUri(null); |
| } |
| mAvatarView.setImageDrawable(avatarDrawable); |
| mAvatarView.setVisibility(View.VISIBLE); |
| } |
| |
| private void updateFromView() { |
| mFromView.setText(formatMessage()); |
| updateAvatarView(); |
| } |
| |
| public void onUpdate(Contact updated) { |
| if (Log.isLoggable(LogTag.CONTACT, Log.DEBUG)) { |
| Log.v(TAG, "onUpdate: " + this + " contact: " + updated); |
| } |
| mHandler.post(new Runnable() { |
| public void run() { |
| updateFromView(); |
| } |
| }); |
| } |
| |
| public final void bind(Context context, final Conversation conversation) { |
| //if (DEBUG) Log.v(TAG, "bind()"); |
| |
| mConversation = conversation; |
| |
| updateBackground(); |
| |
| LayoutParams attachmentLayout = (LayoutParams)mAttachmentView.getLayoutParams(); |
| boolean hasError = conversation.hasError(); |
| // When there's an error icon, the attachment icon is left of the error icon. |
| // When there is not an error icon, the attachment icon is left of the date text. |
| // As far as I know, there's no way to specify that relationship in xml. |
| if (hasError) { |
| attachmentLayout.addRule(RelativeLayout.LEFT_OF, R.id.error); |
| } else { |
| attachmentLayout.addRule(RelativeLayout.LEFT_OF, R.id.date); |
| } |
| |
| boolean hasAttachment = conversation.hasAttachment(); |
| mAttachmentView.setVisibility(hasAttachment ? VISIBLE : GONE); |
| |
| // Date |
| mDateView.setText(MessageUtils.formatTimeStampString(context, conversation.getDate())); |
| |
| // From. |
| mFromView.setText(formatMessage()); |
| |
| // Register for updates in changes of any of the contacts in this conversation. |
| ContactList contacts = conversation.getRecipients(); |
| |
| if (Log.isLoggable(LogTag.CONTACT, Log.DEBUG)) { |
| Log.v(TAG, "bind: contacts.addListeners " + this); |
| } |
| Contact.addListener(this); |
| |
| // Subject |
| SmileyParser parser = SmileyParser.getInstance(); |
| mSubjectView.setText(parser.addSmileySpans(conversation.getSnippet())); |
| LayoutParams subjectLayout = (LayoutParams)mSubjectView.getLayoutParams(); |
| // We have to make the subject left of whatever optional items are shown on the right. |
| subjectLayout.addRule(RelativeLayout.LEFT_OF, hasAttachment ? R.id.attachment : |
| (hasError ? R.id.error : R.id.date)); |
| |
| // Transmission error indicator. |
| mErrorIndicator.setVisibility(hasError ? VISIBLE : GONE); |
| |
| updateAvatarView(); |
| } |
| |
| private void updateBackground() { |
| int backgroundId; |
| if (mConversation.isChecked()) { |
| backgroundId = R.drawable.list_selected_holo_light; |
| } else if (mConversation.hasUnreadMessages()) { |
| backgroundId = R.drawable.conversation_item_background_unread; |
| } else { |
| backgroundId = R.drawable.conversation_item_background_read; |
| } |
| Drawable background = mContext.getResources().getDrawable(backgroundId); |
| setBackground(background); |
| } |
| |
| public final void unbind() { |
| if (Log.isLoggable(LogTag.CONTACT, Log.DEBUG)) { |
| Log.v(TAG, "unbind: contacts.removeListeners " + this); |
| } |
| // Unregister contact update callbacks. |
| Contact.removeListener(this); |
| } |
| |
| public void setChecked(boolean checked) { |
| mConversation.setIsChecked(checked); |
| updateBackground(); |
| } |
| |
| public boolean isChecked() { |
| return mConversation.isChecked(); |
| } |
| |
| public void toggle() { |
| mConversation.setIsChecked(!mConversation.isChecked()); |
| } |
| } |