Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2008 Esmertec AG.
      3  * Copyright (C) 2008 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.mms.ui;
     19 
     20 import java.util.Map;
     21 import java.util.regex.Matcher;
     22 import java.util.regex.Pattern;
     23 
     24 import android.app.AlertDialog;
     25 import android.content.Context;
     26 import android.content.DialogInterface;
     27 import android.content.Intent;
     28 import android.graphics.Bitmap;
     29 import android.graphics.BitmapFactory;
     30 import android.graphics.Canvas;
     31 import android.graphics.Paint;
     32 import android.graphics.Typeface;
     33 import android.graphics.Paint.FontMetricsInt;
     34 import android.graphics.drawable.Drawable;
     35 import android.net.Uri;
     36 import android.os.Handler;
     37 import android.os.Message;
     38 import android.provider.Browser;
     39 import android.provider.Telephony.Mms;
     40 import android.provider.Telephony.MmsSms;
     41 import android.provider.Telephony.Sms;
     42 import android.telephony.PhoneNumberUtils;
     43 import android.telephony.TelephonyManager;
     44 import android.text.Html;
     45 import android.text.Layout;
     46 import android.text.Spannable;
     47 import android.text.SpannableStringBuilder;
     48 import android.text.TextUtils;
     49 import android.text.method.HideReturnsTransformationMethod;
     50 import android.text.style.ForegroundColorSpan;
     51 import android.text.style.LeadingMarginSpan;
     52 import android.text.style.LineHeightSpan;
     53 import android.text.style.StyleSpan;
     54 import android.text.style.TextAppearanceSpan;
     55 import android.text.style.URLSpan;
     56 import android.util.AttributeSet;
     57 import android.util.Log;
     58 import android.view.View;
     59 import android.view.ViewGroup;
     60 import android.view.View.OnClickListener;
     61 import android.widget.ArrayAdapter;
     62 import android.widget.Button;
     63 import android.widget.ImageButton;
     64 import android.widget.ImageView;
     65 import android.widget.LinearLayout;
     66 import android.widget.QuickContactBadge;
     67 import android.widget.TextView;
     68 
     69 import com.android.mms.MmsApp;
     70 import com.android.mms.R;
     71 import com.android.mms.data.WorkingMessage;
     72 import com.android.mms.transaction.Transaction;
     73 import com.android.mms.transaction.TransactionBundle;
     74 import com.android.mms.transaction.TransactionService;
     75 import com.android.mms.util.DownloadManager;
     76 import com.android.mms.util.SmileyParser;
     77 import com.google.android.mms.ContentType;
     78 import com.google.android.mms.pdu.PduHeaders;
     79 
     80 /**
     81  * This class provides view of a message in the messages list.
     82  */
     83 public class MessageListItem extends LinearLayout implements
     84         SlideViewInterface, OnClickListener {
     85     public static final String EXTRA_URLS = "com.android.mms.ExtraUrls";
     86 
     87     private static final String TAG = "MessageListItem";
     88     private static final StyleSpan STYLE_BOLD = new StyleSpan(Typeface.BOLD);
     89 
     90     static final int MSG_LIST_EDIT_MMS   = 1;
     91     static final int MSG_LIST_EDIT_SMS   = 2;
     92 
     93     private View mMsgListItem;
     94     private View mMmsView;
     95     private ImageView mImageView;
     96     private ImageView mLockedIndicator;
     97     private ImageView mDeliveredIndicator;
     98     private ImageView mDetailsIndicator;
     99     private ImageButton mSlideShowButton;
    100     private TextView mBodyTextView;
    101     private Button mDownloadButton;
    102     private TextView mDownloadingLabel;
    103     private QuickContactBadge mAvatar;
    104     private Handler mHandler;
    105     private MessageItem mMessageItem;
    106 
    107     public MessageListItem(Context context) {
    108         super(context);
    109     }
    110 
    111     public MessageListItem(Context context, AttributeSet attrs) {
    112         super(context, attrs);
    113 
    114         int color = mContext.getResources().getColor(R.color.timestamp_color);
    115         mColorSpan = new ForegroundColorSpan(color);
    116     }
    117 
    118     @Override
    119     protected void onFinishInflate() {
    120         super.onFinishInflate();
    121 
    122         mMsgListItem = findViewById(R.id.msg_list_item);
    123         mBodyTextView = (TextView) findViewById(R.id.text_view);
    124         mLockedIndicator = (ImageView) findViewById(R.id.locked_indicator);
    125         mDeliveredIndicator = (ImageView) findViewById(R.id.delivered_indicator);
    126         mDetailsIndicator = (ImageView) findViewById(R.id.details_indicator);
    127         mAvatar = (QuickContactBadge) findViewById(R.id.avatar);
    128 
    129         ViewGroup.MarginLayoutParams badgeParams = (MarginLayoutParams)mAvatar.getLayoutParams();
    130         final int badgeWidth = badgeParams.width + badgeParams.rightMargin + badgeParams.leftMargin;
    131 
    132         int lineHeight = mBodyTextView.getLineHeight();
    133         int effectiveBadgeHeight = badgeParams.height + badgeParams.topMargin - mBodyTextView.getPaddingTop();
    134         final int indentLineCount = (int) ((effectiveBadgeHeight-1) / lineHeight) + 1;
    135 
    136         mLeadingMarginSpan = new LeadingMarginSpan.LeadingMarginSpan2() {
    137             public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
    138                     int top, int baseline, int bottom, CharSequence text,
    139                     int start, int end, boolean first, Layout layout) {
    140                 // no op
    141             }
    142 
    143             public int getLeadingMargin(boolean first) {
    144                 return first ? badgeWidth : 0;
    145             }
    146 
    147             public int getLeadingMarginLineCount() {
    148                 return indentLineCount;
    149             }
    150         };
    151 
    152     }
    153 
    154     public void bind(MessageListAdapter.AvatarCache avatarCache, MessageItem msgItem) {
    155         mMessageItem = msgItem;
    156 
    157         setLongClickable(false);
    158 
    159         switch (msgItem.mMessageType) {
    160             case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
    161                 bindNotifInd(msgItem);
    162                 break;
    163             default:
    164                 bindCommonMessage(avatarCache, msgItem);
    165                 break;
    166         }
    167     }
    168 
    169     public MessageItem getMessageItem() {
    170         return mMessageItem;
    171     }
    172 
    173     public void setMsgListItemHandler(Handler handler) {
    174         mHandler = handler;
    175     }
    176 
    177     private void bindNotifInd(final MessageItem msgItem) {
    178         hideMmsViewIfNeeded();
    179 
    180         String msgSizeText = mContext.getString(R.string.message_size_label)
    181                                 + String.valueOf((msgItem.mMessageSize + 1023) / 1024)
    182                                 + mContext.getString(R.string.kilobyte);
    183 
    184         mBodyTextView.setText(formatMessage(msgItem, msgItem.mContact, null, msgItem.mSubject,
    185                                             msgSizeText + "\n" + msgItem.mTimestamp,
    186                                             msgItem.mHighlight, msgItem.mTextContentType));
    187 
    188         int state = DownloadManager.getInstance().getState(msgItem.mMessageUri);
    189         switch (state) {
    190             case DownloadManager.STATE_DOWNLOADING:
    191                 inflateDownloadControls();
    192                 mDownloadingLabel.setVisibility(View.VISIBLE);
    193                 mDownloadButton.setVisibility(View.GONE);
    194                 break;
    195             case DownloadManager.STATE_UNSTARTED:
    196             case DownloadManager.STATE_TRANSIENT_FAILURE:
    197             case DownloadManager.STATE_PERMANENT_FAILURE:
    198             default:
    199                 setLongClickable(true);
    200                 inflateDownloadControls();
    201                 mDownloadingLabel.setVisibility(View.GONE);
    202                 mDownloadButton.setVisibility(View.VISIBLE);
    203                 mDownloadButton.setOnClickListener(new OnClickListener() {
    204                     public void onClick(View v) {
    205                         mDownloadingLabel.setVisibility(View.VISIBLE);
    206                         mDownloadButton.setVisibility(View.GONE);
    207                         Intent intent = new Intent(mContext, TransactionService.class);
    208                         intent.putExtra(TransactionBundle.URI, msgItem.mMessageUri.toString());
    209                         intent.putExtra(TransactionBundle.TRANSACTION_TYPE,
    210                                 Transaction.RETRIEVE_TRANSACTION);
    211                         mContext.startService(intent);
    212                     }
    213                 });
    214                 break;
    215         }
    216 
    217         // Hide the indicators.
    218         mLockedIndicator.setVisibility(View.GONE);
    219         mDeliveredIndicator.setVisibility(View.GONE);
    220         mDetailsIndicator.setVisibility(View.GONE);
    221 
    222         drawLeftStatusIndicator(msgItem.mBoxId);
    223     }
    224 
    225     private void bindCommonMessage(final MessageListAdapter.AvatarCache avatarCache, final MessageItem msgItem) {
    226         if (mDownloadButton != null) {
    227             mDownloadButton.setVisibility(View.GONE);
    228             mDownloadingLabel.setVisibility(View.GONE);
    229         }
    230         // Since the message text should be concatenated with the sender's
    231         // address(or name), I have to display it here instead of
    232         // displaying it by the Presenter.
    233         mBodyTextView.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
    234 
    235         String addr = null;
    236         if (!Sms.isOutgoingFolder(msgItem.mBoxId)) {
    237             addr = msgItem.mAddress;
    238         } else {
    239             addr = MmsApp.getApplication().getTelephonyManager().getLine1Number();
    240         }
    241         if (!TextUtils.isEmpty(addr)) {
    242             MessageListAdapter.AvatarCache.ContactData contactData = avatarCache.get(addr);
    243             mAvatar.setImageDrawable(contactData.getAvatar());
    244             Uri contactUri = contactData.getContactUri();
    245             // Since we load the contact info in the background, on the first screenfull of
    246             // messages, it's likely we haven't loaded the contact URI info yet. In that case,
    247             // fall back and use the phone number.
    248             if (contactUri != null) {
    249                 mAvatar.assignContactUri(contactUri);
    250             } else {
    251                 mAvatar.assignContactFromPhone(addr, true);
    252             }
    253         } else {
    254             mAvatar.setImageDrawable(null);
    255             mAvatar.assignContactUri(null);
    256         }
    257 
    258         // Get and/or lazily set the formatted message from/on the
    259         // MessageItem.  Because the MessageItem instances come from a
    260         // cache (currently of size ~50), the hit rate on avoiding the
    261         // expensive formatMessage() call is very high.
    262         CharSequence formattedMessage = msgItem.getCachedFormattedMessage();
    263         if (formattedMessage == null) {
    264             formattedMessage = formatMessage(msgItem, msgItem.mContact, msgItem.mBody,
    265                                              msgItem.mSubject, msgItem.mTimestamp,
    266                                              msgItem.mHighlight, msgItem.mTextContentType);
    267         }
    268         mBodyTextView.setText(formattedMessage);
    269 
    270         if (msgItem.isSms()) {
    271             hideMmsViewIfNeeded();
    272         } else {
    273             Presenter presenter = PresenterFactory.getPresenter(
    274                     "MmsThumbnailPresenter", mContext,
    275                     this, msgItem.mSlideshow);
    276             presenter.present();
    277 
    278             if (msgItem.mAttachmentType != WorkingMessage.TEXT) {
    279                 inflateMmsView();
    280                 mMmsView.setVisibility(View.VISIBLE);
    281                 setOnClickListener(msgItem);
    282                 drawPlaybackButton(msgItem);
    283             } else {
    284                 hideMmsViewIfNeeded();
    285             }
    286         }
    287 
    288         drawLeftStatusIndicator(msgItem.mBoxId);
    289         drawRightStatusIndicator(msgItem);
    290 
    291         requestLayout();
    292     }
    293 
    294     private void hideMmsViewIfNeeded() {
    295         if (mMmsView != null) {
    296             mMmsView.setVisibility(View.GONE);
    297         }
    298     }
    299 
    300     public void startAudio() {
    301         // TODO Auto-generated method stub
    302     }
    303 
    304     public void startVideo() {
    305         // TODO Auto-generated method stub
    306     }
    307 
    308     public void setAudio(Uri audio, String name, Map<String, ?> extras) {
    309         // TODO Auto-generated method stub
    310     }
    311 
    312     public void setImage(String name, Bitmap bitmap) {
    313         inflateMmsView();
    314 
    315         try {
    316             if (null == bitmap) {
    317                 bitmap = BitmapFactory.decodeResource(getResources(),
    318                         R.drawable.ic_missing_thumbnail_picture);
    319             }
    320             mImageView.setImageBitmap(bitmap);
    321             mImageView.setVisibility(VISIBLE);
    322         } catch (java.lang.OutOfMemoryError e) {
    323             Log.e(TAG, "setImage: out of memory: ", e);
    324         }
    325     }
    326 
    327     private void inflateMmsView() {
    328         if (mMmsView == null) {
    329             //inflate the surrounding view_stub
    330             findViewById(R.id.mms_layout_view_stub).setVisibility(VISIBLE);
    331 
    332             mMmsView = findViewById(R.id.mms_view);
    333             mImageView = (ImageView) findViewById(R.id.image_view);
    334             mSlideShowButton = (ImageButton) findViewById(R.id.play_slideshow_button);
    335         }
    336     }
    337 
    338     private void inflateDownloadControls() {
    339         if (mDownloadButton == null) {
    340             //inflate the download controls
    341             findViewById(R.id.mms_downloading_view_stub).setVisibility(VISIBLE);
    342             mDownloadButton = (Button) findViewById(R.id.btn_download_msg);
    343             mDownloadingLabel = (TextView) findViewById(R.id.label_downloading);
    344         }
    345     }
    346 
    347     private LeadingMarginSpan mLeadingMarginSpan;
    348 
    349     private LineHeightSpan mSpan = new LineHeightSpan() {
    350         public void chooseHeight(CharSequence text, int start,
    351                 int end, int spanstartv, int v, FontMetricsInt fm) {
    352             fm.ascent -= 10;
    353         }
    354     };
    355 
    356     TextAppearanceSpan mTextSmallSpan =
    357         new TextAppearanceSpan(mContext, android.R.style.TextAppearance_Small);
    358 
    359     ForegroundColorSpan mColorSpan = null;  // set in ctor
    360 
    361     private CharSequence formatMessage(MessageItem msgItem, String contact, String body,
    362                                        String subject, String timestamp, Pattern highlight,
    363                                        String contentType) {
    364         CharSequence template = mContext.getResources().getText(R.string.name_colon);
    365         SpannableStringBuilder buf =
    366             new SpannableStringBuilder(TextUtils.replace(template,
    367                 new String[] { "%s" },
    368                 new CharSequence[] { contact }));
    369 
    370         boolean hasSubject = !TextUtils.isEmpty(subject);
    371         if (hasSubject) {
    372             buf.append(mContext.getResources().getString(R.string.inline_subject, subject));
    373         }
    374 
    375         if (!TextUtils.isEmpty(body)) {
    376             // Converts html to spannable if ContentType is "text/html".
    377             if (contentType != null && ContentType.TEXT_HTML.equals(contentType)) {
    378                 buf.append("\n");
    379                 buf.append(Html.fromHtml(body));
    380             } else {
    381                 if (hasSubject) {
    382                     buf.append(" - ");
    383                 }
    384                 SmileyParser parser = SmileyParser.getInstance();
    385                 buf.append(parser.addSmileySpans(body));
    386             }
    387         }
    388         // If we're in the process of sending a message (i.e. pending), then we show a "Sending..."
    389         // string in place of the timestamp.
    390         if (msgItem.isSending()) {
    391             timestamp = mContext.getResources().getString(R.string.sending_message);
    392         }
    393         // We always show two lines because the optional icon bottoms are aligned with the
    394         // bottom of the text field, assuming there are two lines for the message and the sent time.
    395         buf.append("\n");
    396         int startOffset = buf.length();
    397 
    398         startOffset = buf.length();
    399         buf.append(TextUtils.isEmpty(timestamp) ? " " : timestamp);
    400 
    401         buf.setSpan(mTextSmallSpan, startOffset, buf.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    402         buf.setSpan(mSpan, startOffset+1, buf.length(), 0);
    403 
    404         // Make the timestamp text not as dark
    405         buf.setSpan(mColorSpan, startOffset, buf.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    406 
    407         if (highlight != null) {
    408             Matcher m = highlight.matcher(buf.toString());
    409             while (m.find()) {
    410                 buf.setSpan(new StyleSpan(Typeface.BOLD), m.start(), m.end(), 0);
    411             }
    412         }
    413         buf.setSpan(mLeadingMarginSpan, 0, buf.length(), 0);
    414         return buf;
    415     }
    416 
    417     private void drawPlaybackButton(MessageItem msgItem) {
    418         switch (msgItem.mAttachmentType) {
    419             case WorkingMessage.SLIDESHOW:
    420             case WorkingMessage.AUDIO:
    421             case WorkingMessage.VIDEO:
    422                 // Show the 'Play' button and bind message info on it.
    423                 mSlideShowButton.setTag(msgItem);
    424                 // Set call-back for the 'Play' button.
    425                 mSlideShowButton.setOnClickListener(this);
    426                 mSlideShowButton.setVisibility(View.VISIBLE);
    427                 setLongClickable(true);
    428 
    429                 // When we show the mSlideShowButton, this list item's onItemClickListener doesn't
    430                 // get called. (It gets set in ComposeMessageActivity:
    431                 // mMsgListView.setOnItemClickListener) Here we explicitly set the item's
    432                 // onClickListener. It allows the item to respond to embedded html links and at the
    433                 // same time, allows the slide show play button to work.
    434                 setOnClickListener(new OnClickListener() {
    435                     public void onClick(View v) {
    436                         onMessageListItemClick();
    437                     }
    438                 });
    439                 break;
    440             default:
    441                 mSlideShowButton.setVisibility(View.GONE);
    442                 break;
    443         }
    444     }
    445 
    446     // OnClick Listener for the playback button
    447     public void onClick(View v) {
    448         MessageItem mi = (MessageItem) v.getTag();
    449         switch (mi.mAttachmentType) {
    450             case WorkingMessage.VIDEO:
    451             case WorkingMessage.AUDIO:
    452             case WorkingMessage.SLIDESHOW:
    453                 MessageUtils.viewMmsMessageAttachment(mContext, mi.mMessageUri, mi.mSlideshow);
    454                 break;
    455         }
    456     }
    457 
    458     public void onMessageListItemClick() {
    459         URLSpan[] spans = mBodyTextView.getUrls();
    460 
    461         if (spans.length == 0) {
    462             // Do nothing.
    463         } else if (spans.length == 1) {
    464             Uri uri = Uri.parse(spans[0].getURL());
    465             Intent intent = new Intent(Intent.ACTION_VIEW, uri);
    466             intent.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName());
    467             intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    468             mContext.startActivity(intent);
    469         } else {
    470             final java.util.ArrayList<String> urls = MessageUtils.extractUris(spans);
    471 
    472             ArrayAdapter<String> adapter =
    473                 new ArrayAdapter<String>(mContext, android.R.layout.select_dialog_item, urls) {
    474                 public View getView(int position, View convertView, ViewGroup parent) {
    475                     View v = super.getView(position, convertView, parent);
    476                     try {
    477                         String url = getItem(position).toString();
    478                         TextView tv = (TextView) v;
    479                         Drawable d = mContext.getPackageManager().getActivityIcon(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
    480                         if (d != null) {
    481                             d.setBounds(0, 0, d.getIntrinsicHeight(), d.getIntrinsicHeight());
    482                             tv.setCompoundDrawablePadding(10);
    483                             tv.setCompoundDrawables(d, null, null, null);
    484                         }
    485                         final String telPrefix = "tel:";
    486                         if (url.startsWith(telPrefix)) {
    487                             url = PhoneNumberUtils.formatNumber(url.substring(telPrefix.length()));
    488                         }
    489                         tv.setText(url);
    490                     } catch (android.content.pm.PackageManager.NameNotFoundException ex) {
    491                         ;
    492                     }
    493                     return v;
    494                 }
    495             };
    496 
    497             AlertDialog.Builder b = new AlertDialog.Builder(mContext);
    498 
    499             DialogInterface.OnClickListener click = new DialogInterface.OnClickListener() {
    500                 public final void onClick(DialogInterface dialog, int which) {
    501                     if (which >= 0) {
    502                         Uri uri = Uri.parse(urls.get(which));
    503                         Intent intent = new Intent(Intent.ACTION_VIEW, uri);
    504                         intent.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName());
    505                         intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    506                         mContext.startActivity(intent);
    507                     }
    508                     dialog.dismiss();
    509                 }
    510             };
    511 
    512             b.setTitle(R.string.select_link_title);
    513             b.setCancelable(true);
    514             b.setAdapter(adapter, click);
    515 
    516             b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
    517                 public final void onClick(DialogInterface dialog, int which) {
    518                     dialog.dismiss();
    519                 }
    520             });
    521 
    522             b.show();
    523         }
    524     }
    525 
    526 
    527     private void setOnClickListener(final MessageItem msgItem) {
    528         switch(msgItem.mAttachmentType) {
    529         case WorkingMessage.IMAGE:
    530         case WorkingMessage.VIDEO:
    531             mImageView.setOnClickListener(new OnClickListener() {
    532                 public void onClick(View v) {
    533                     MessageUtils.viewMmsMessageAttachment(mContext, null, msgItem.mSlideshow);
    534                 }
    535             });
    536             mImageView.setOnLongClickListener(new OnLongClickListener() {
    537                 public boolean onLongClick(View v) {
    538                     return v.showContextMenu();
    539                 }
    540             });
    541             break;
    542 
    543         default:
    544             mImageView.setOnClickListener(null);
    545             break;
    546         }
    547     }
    548 
    549     private void drawLeftStatusIndicator(int msgBoxId) {
    550         switch (msgBoxId) {
    551             case Mms.MESSAGE_BOX_INBOX:
    552                 mMsgListItem.setBackgroundResource(R.drawable.listitem_background_lightblue);
    553                 break;
    554 
    555             case Mms.MESSAGE_BOX_DRAFTS:
    556             case Sms.MESSAGE_TYPE_FAILED:
    557             case Sms.MESSAGE_TYPE_QUEUED:
    558             case Mms.MESSAGE_BOX_OUTBOX:
    559                 mMsgListItem.setBackgroundResource(R.drawable.listitem_background);
    560                 break;
    561 
    562             default:
    563                 mMsgListItem.setBackgroundResource(R.drawable.listitem_background);
    564                 break;
    565         }
    566     }
    567 
    568     private void setErrorIndicatorClickListener(final MessageItem msgItem) {
    569         String type = msgItem.mType;
    570         final int what;
    571         if (type.equals("sms")) {
    572             what = MSG_LIST_EDIT_SMS;
    573         } else {
    574             what = MSG_LIST_EDIT_MMS;
    575         }
    576         mDeliveredIndicator.setOnClickListener(new OnClickListener() {
    577             public void onClick(View v) {
    578                 if (null != mHandler) {
    579                     Message msg = Message.obtain(mHandler, what);
    580                     msg.obj = new Long(msgItem.mMsgId);
    581                     msg.sendToTarget();
    582                 }
    583             }
    584         });
    585     }
    586 
    587     private void drawRightStatusIndicator(MessageItem msgItem) {
    588         // Locked icon
    589         if (msgItem.mLocked) {
    590             mLockedIndicator.setImageResource(R.drawable.ic_lock_message_sms);
    591             mLockedIndicator.setVisibility(View.VISIBLE);
    592         } else {
    593             mLockedIndicator.setVisibility(View.GONE);
    594         }
    595 
    596         // Delivery icon
    597         if (msgItem.isOutgoingMessage() && msgItem.isFailedMessage()) {
    598             mDeliveredIndicator.setImageResource(R.drawable.ic_list_alert_sms_failed);
    599             setErrorIndicatorClickListener(msgItem);
    600             mDeliveredIndicator.setVisibility(View.VISIBLE);
    601         } else if (msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.FAILED) {
    602             mDeliveredIndicator.setImageResource(R.drawable.ic_list_alert_sms_failed);
    603             mDeliveredIndicator.setVisibility(View.VISIBLE);
    604         } else if (msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.RECEIVED) {
    605             mDeliveredIndicator.setImageResource(R.drawable.ic_sms_mms_delivered);
    606             mDeliveredIndicator.setVisibility(View.VISIBLE);
    607         } else {
    608             mDeliveredIndicator.setVisibility(View.GONE);
    609         }
    610 
    611         // Message details icon
    612         if (msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.INFO || msgItem.mReadReport) {
    613             mDetailsIndicator.setImageResource(R.drawable.ic_sms_mms_details);
    614             mDetailsIndicator.setVisibility(View.VISIBLE);
    615         } else {
    616             mDetailsIndicator.setVisibility(View.GONE);
    617         }
    618     }
    619 
    620     public void setImageRegionFit(String fit) {
    621         // TODO Auto-generated method stub
    622     }
    623 
    624     public void setImageVisibility(boolean visible) {
    625         // TODO Auto-generated method stub
    626     }
    627 
    628     public void setText(String name, String text) {
    629         // TODO Auto-generated method stub
    630     }
    631 
    632     public void setTextVisibility(boolean visible) {
    633         // TODO Auto-generated method stub
    634     }
    635 
    636     public void setVideo(String name, Uri video) {
    637         inflateMmsView();
    638 
    639         try {
    640             Bitmap bitmap = VideoAttachmentView.createVideoThumbnail(mContext, video);
    641             if (null == bitmap) {
    642                 bitmap = BitmapFactory.decodeResource(getResources(),
    643                         R.drawable.ic_missing_thumbnail_video);
    644             }
    645             mImageView.setImageBitmap(bitmap);
    646             mImageView.setVisibility(VISIBLE);
    647         } catch (java.lang.OutOfMemoryError e) {
    648             Log.e(TAG, "setVideo: out of memory: ", e);
    649         }
    650     }
    651 
    652     public void setVideoVisibility(boolean visible) {
    653         // TODO Auto-generated method stub
    654     }
    655 
    656     public void stopAudio() {
    657         // TODO Auto-generated method stub
    658     }
    659 
    660     public void stopVideo() {
    661         // TODO Auto-generated method stub
    662     }
    663 
    664     public void reset() {
    665         if (mImageView != null) {
    666             mImageView.setVisibility(GONE);
    667         }
    668     }
    669 
    670     public void setVisibility(boolean visible) {
    671         // TODO Auto-generated method stub
    672     }
    673 
    674     public void pauseAudio() {
    675         // TODO Auto-generated method stub
    676 
    677     }
    678 
    679     public void pauseVideo() {
    680         // TODO Auto-generated method stub
    681 
    682     }
    683 
    684     public void seekAudio(int seekTo) {
    685         // TODO Auto-generated method stub
    686 
    687     }
    688 
    689     public void seekVideo(int seekTo) {
    690         // TODO Auto-generated method stub
    691 
    692     }
    693 }
    694