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 com.google.android.mms.ContentType;
     21 import com.android.mms.ExceedMessageSizeException;
     22 import com.google.android.mms.MmsException;
     23 import com.android.mms.MmsConfig;
     24 import com.android.mms.R;
     25 import com.android.mms.ResolutionException;
     26 import com.android.mms.UnsupportContentTypeException;
     27 import com.android.mms.model.IModelChangedObserver;
     28 import com.android.mms.model.LayoutModel;
     29 import com.android.mms.model.Model;
     30 import com.android.mms.model.SlideModel;
     31 import com.android.mms.model.SlideshowModel;
     32 import com.google.android.mms.pdu.PduBody;
     33 import com.google.android.mms.pdu.PduPart;
     34 import com.google.android.mms.pdu.PduPersister;
     35 import com.android.mms.ui.BasicSlideEditorView.OnTextChangedListener;
     36 import com.android.mms.ui.MessageUtils.ResizeImageResultCallback;
     37 
     38 import android.app.Activity;
     39 import android.app.AlertDialog;
     40 import android.content.ContentUris;
     41 import android.content.Context;
     42 import android.content.DialogInterface;
     43 import android.content.Intent;
     44 import android.content.res.Resources;
     45 import android.graphics.Bitmap;
     46 import android.media.RingtoneManager;
     47 import android.net.Uri;
     48 import android.os.Bundle;
     49 import android.os.Handler;
     50 import android.provider.MediaStore;
     51 import android.provider.Settings;
     52 import android.text.TextUtils;
     53 import android.util.Config;
     54 import android.util.Log;
     55 import android.view.Menu;
     56 import android.view.MenuItem;
     57 import android.view.SubMenu;
     58 import android.view.View;
     59 import android.view.View.OnClickListener;
     60 import android.widget.Button;
     61 import android.widget.ImageButton;
     62 import android.widget.Toast;
     63 
     64 /**
     65  * This activity allows user to edit the contents of a slide.
     66  */
     67 public class SlideEditorActivity extends Activity {
     68     private static final String TAG = "SlideEditorActivity";
     69     private static final boolean DEBUG = false;
     70     private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
     71 
     72     // Key for extra data.
     73     public static final String SLIDE_INDEX = "slide_index";
     74 
     75     // Menu ids.
     76     private final static int MENU_REMOVE_TEXT       = 0;
     77     private final static int MENU_ADD_PICTURE       = 1;
     78     private final static int MENU_TAKE_PICTURE      = 2;
     79     private final static int MENU_DEL_PICTURE       = 3;
     80     private final static int MENU_ADD_AUDIO         = 4;
     81     private final static int MENU_DEL_AUDIO         = 5;
     82     private final static int MENU_ADD_VIDEO         = 6;
     83     private final static int MENU_ADD_SLIDE         = 7;
     84     private final static int MENU_DEL_VIDEO         = 8;
     85     private final static int MENU_LAYOUT            = 9;
     86     private final static int MENU_DURATION          = 10;
     87     private final static int MENU_PREVIEW_SLIDESHOW = 11;
     88     private final static int MENU_RECORD_SOUND      = 12;
     89     private final static int MENU_SUB_AUDIO         = 13;
     90 
     91     // Request code.
     92     private final static int REQUEST_CODE_EDIT_TEXT          = 0;
     93     private final static int REQUEST_CODE_CHANGE_PICTURE     = 1;
     94     private final static int REQUEST_CODE_TAKE_PICTURE       = 2;
     95     private final static int REQUEST_CODE_CHANGE_MUSIC       = 3;
     96     private final static int REQUEST_CODE_RECORD_SOUND       = 4;
     97     private final static int REQUEST_CODE_CHANGE_VIDEO       = 5;
     98     private final static int REQUEST_CODE_CHANGE_DURATION    = 6;
     99 
    100     // number of items in the duration selector dialog that directly map from
    101     // item index to duration in seconds (duration = index + 1)
    102     private final static int NUM_DIRECT_DURATIONS = 10;
    103 
    104     private ImageButton mNextSlide;
    105     private ImageButton mPreSlide;
    106     private Button mPreview;
    107     private Button mReplaceImage;
    108     private Button mRemoveSlide;
    109     private Button mDone;
    110     private BasicSlideEditorView mSlideView;
    111 
    112     private SlideshowModel mSlideshowModel;
    113     private SlideshowEditor mSlideshowEditor;
    114     private SlideshowPresenter mPresenter;
    115     private boolean mDirty;
    116 
    117     private int mPosition;
    118     private Uri mUri;
    119 
    120     private final static String MESSAGE_URI = "message_uri";
    121 
    122     @Override
    123     protected void onCreate(Bundle savedInstanceState) {
    124         super.onCreate(savedInstanceState);
    125         setContentView(R.layout.edit_slide_activity);
    126 
    127         mSlideView = (BasicSlideEditorView) findViewById(R.id.slide_editor_view);
    128         mSlideView.setOnTextChangedListener(mOnTextChangedListener);
    129 
    130         mPreSlide = (ImageButton) findViewById(R.id.pre_slide_button);
    131         mPreSlide.setOnClickListener(mOnNavigateBackward);
    132 
    133         mNextSlide = (ImageButton) findViewById(R.id.next_slide_button);
    134         mNextSlide.setOnClickListener(mOnNavigateForward);
    135 
    136         mPreview = (Button) findViewById(R.id.preview_button);
    137         mPreview.setOnClickListener(mOnPreview);
    138 
    139         mReplaceImage = (Button) findViewById(R.id.replace_image_button);
    140         mReplaceImage.setOnClickListener(mOnReplaceImage);
    141 
    142         mRemoveSlide = (Button) findViewById(R.id.remove_slide_button);
    143         mRemoveSlide.setOnClickListener(mOnRemoveSlide);
    144 
    145         mDone = (Button) findViewById(R.id.done_button);
    146         mDone.setOnClickListener(mDoneClickListener);
    147 
    148         initActivityState(savedInstanceState, getIntent());
    149 
    150         try {
    151             mSlideshowModel = SlideshowModel.createFromMessageUri(this, mUri);
    152             // Register an observer to watch whether the data model is changed.
    153             mSlideshowModel.registerModelChangedObserver(mModelChangedObserver);
    154             mSlideshowEditor = new SlideshowEditor(this, mSlideshowModel);
    155             mPresenter = (SlideshowPresenter) PresenterFactory.getPresenter(
    156                     "SlideshowPresenter", this, mSlideView, mSlideshowModel);
    157 
    158             // Sanitize mPosition
    159             if (mPosition >= mSlideshowModel.size()) {
    160                 mPosition = Math.max(0, mSlideshowModel.size() - 1);
    161             } else if (mPosition < 0) {
    162                 mPosition = 0;
    163             }
    164 
    165             showCurrentSlide();
    166         } catch (MmsException e) {
    167             Log.e(TAG, "Create SlideshowModel failed!", e);
    168             finish();
    169             return;
    170         }
    171     }
    172 
    173     private void initActivityState(Bundle savedInstanceState, Intent intent) {
    174         if (savedInstanceState != null) {
    175             mUri = (Uri) savedInstanceState.getParcelable(MESSAGE_URI);
    176             mPosition = savedInstanceState.getInt(SLIDE_INDEX, 0);
    177         } else {
    178             mUri = intent.getData();
    179             mPosition = intent.getIntExtra(SLIDE_INDEX, 0);
    180         }
    181     }
    182 
    183     @Override
    184     protected void onSaveInstanceState(Bundle outState) {
    185         super.onSaveInstanceState(outState);
    186 
    187         outState.putInt(SLIDE_INDEX, mPosition);
    188         outState.putParcelable(MESSAGE_URI, mUri);
    189     }
    190 
    191     @Override
    192     protected void onPause()  {
    193         super.onPause();
    194 
    195         synchronized (this) {
    196             if (mDirty) {
    197                 try {
    198                     PduBody pb = mSlideshowModel.toPduBody();
    199                     PduPersister.getPduPersister(this).updateParts(mUri, pb);
    200                     mSlideshowModel.sync(pb);
    201                 }  catch (MmsException e) {
    202                     Log.e(TAG, "Cannot update the message: " + mUri, e);
    203                 }
    204             }
    205         }
    206     }
    207 
    208     @Override
    209     protected void onDestroy() {
    210         super.onDestroy();
    211 
    212         if (mSlideshowModel != null) {
    213             mSlideshowModel.unregisterModelChangedObserver(
    214                     mModelChangedObserver);
    215         }
    216     }
    217 
    218     private final IModelChangedObserver mModelChangedObserver =
    219         new IModelChangedObserver() {
    220             public void onModelChanged(Model model, boolean dataChanged) {
    221                 synchronized (SlideEditorActivity.this) {
    222                     mDirty = true;
    223                 }
    224                 setResult(RESULT_OK);
    225             }
    226         };
    227 
    228     private final OnClickListener mOnRemoveSlide = new OnClickListener() {
    229         public void onClick(View v) {
    230             // Validate mPosition
    231             if (mPosition >= 0 && mPosition < mSlideshowModel.size()) {
    232                 mSlideshowEditor.removeSlide(mPosition);
    233                 int size = mSlideshowModel.size();
    234                 if (size > 0) {
    235                     if (mPosition >= size) {
    236                         mPosition--;
    237                     }
    238                     showCurrentSlide();
    239                 } else {
    240                     finish();
    241                     return;
    242                 }
    243             }
    244         }
    245     };
    246 
    247     private final OnTextChangedListener mOnTextChangedListener = new OnTextChangedListener() {
    248         public void onTextChanged(String s) {
    249             if (!isFinishing()) {
    250                 mSlideshowEditor.changeText(mPosition, s);
    251             }
    252         }
    253     };
    254 
    255     private final OnClickListener mOnPreview = new OnClickListener() {
    256         public void onClick(View v) {
    257             previewSlideshow();
    258         }
    259     };
    260 
    261     private final OnClickListener mOnReplaceImage = new OnClickListener() {
    262         public void onClick(View v) {
    263             SlideModel slide = mSlideshowModel.get(mPosition);
    264             if (slide != null && slide.hasVideo()) {
    265                 Toast.makeText(SlideEditorActivity.this, R.string.cannot_add_picture_and_video,
    266                         Toast.LENGTH_SHORT).show();
    267                 return;
    268             }
    269             Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
    270             intent.setType(ContentType.IMAGE_UNSPECIFIED);
    271             startActivityForResult(intent, REQUEST_CODE_CHANGE_PICTURE);
    272         }
    273     };
    274 
    275     private final OnClickListener mOnNavigateBackward = new OnClickListener() {
    276         public void onClick(View v) {
    277             if (mPosition > 0) {
    278                 mPosition --;
    279                 showCurrentSlide();
    280             }
    281         }
    282     };
    283 
    284     private final OnClickListener mOnNavigateForward = new OnClickListener() {
    285         public void onClick(View v) {
    286             if (mPosition < mSlideshowModel.size() - 1) {
    287                 mPosition ++;
    288                 showCurrentSlide();
    289             }
    290         }
    291     };
    292 
    293     private final OnClickListener mDoneClickListener = new OnClickListener() {
    294         public void onClick(View v) {
    295             Intent data = new Intent();
    296             data.putExtra("done", true);
    297             setResult(RESULT_OK, data);
    298             finish();
    299         }
    300     };
    301 
    302     private void previewSlideshow() {
    303         MessageUtils.viewMmsMessageAttachment(SlideEditorActivity.this, mUri, mSlideshowModel);
    304     }
    305 
    306     private void updateTitle() {
    307         setTitle(getString(R.string.slide_show_part, (mPosition + 1), mSlideshowModel.size()));
    308     }
    309 
    310     @Override
    311     public boolean onPrepareOptionsMenu(Menu menu) {
    312         if (isFinishing()) {
    313             return false;
    314         }
    315         menu.clear();
    316 
    317         SlideModel slide = mSlideshowModel.get(mPosition);
    318 
    319         if (slide == null) {
    320             return false;
    321         }
    322 
    323         // Preview slideshow.
    324         menu.add(0, MENU_PREVIEW_SLIDESHOW, 0, R.string.preview_slideshow).setIcon(
    325                 com.android.internal.R.drawable.ic_menu_play_clip);
    326 
    327         // Text
    328         if (slide.hasText() && !TextUtils.isEmpty(slide.getText().getText())) {
    329             //"Change text" if text is set.
    330             menu.add(0, MENU_REMOVE_TEXT, 0, R.string.remove_text).setIcon(
    331                     R.drawable.ic_menu_remove_text);
    332         }
    333 
    334         // Picture
    335         if (slide.hasImage()) {
    336             menu.add(0, MENU_DEL_PICTURE, 0, R.string.remove_picture).setIcon(
    337                     R.drawable.ic_menu_remove_picture);
    338         } else if (!slide.hasVideo()) {
    339             menu.add(0, MENU_ADD_PICTURE, 0, R.string.add_picture).setIcon(
    340                     R.drawable.ic_menu_picture);
    341             menu.add(0, MENU_TAKE_PICTURE, 0, R.string.attach_take_photo).setIcon(
    342                     R.drawable.ic_menu_picture);
    343         }
    344 
    345         // Music
    346         if (slide.hasAudio()) {
    347             menu.add(0, MENU_DEL_AUDIO, 0, R.string.remove_music).setIcon(
    348                     R.drawable.ic_menu_remove_sound);
    349         } else if (!slide.hasVideo()) {
    350             if (MmsConfig.getAllowAttachAudio()) {
    351                 SubMenu subMenu = menu.addSubMenu(0, MENU_SUB_AUDIO, 0, R.string.add_music)
    352                     .setIcon(R.drawable.ic_menu_add_sound);
    353                 subMenu.add(0, MENU_ADD_AUDIO, 0, R.string.attach_sound);
    354                 subMenu.add(0, MENU_RECORD_SOUND, 0, R.string.attach_record_sound);
    355             } else {
    356                 menu.add(0, MENU_RECORD_SOUND, 0, R.string.attach_record_sound)
    357                     .setIcon(R.drawable.ic_menu_add_sound);
    358             }
    359         }
    360 
    361         // Video
    362         if (slide.hasVideo()) {
    363             menu.add(0, MENU_DEL_VIDEO, 0, R.string.remove_video).setIcon(
    364                     R.drawable.ic_menu_remove_video);
    365         } else if (!slide.hasAudio() && !slide.hasImage()) {
    366             menu.add(0, MENU_ADD_VIDEO, 0, R.string.add_video).setIcon(R.drawable.ic_menu_movie);
    367         }
    368 
    369         // Add slide
    370         menu.add(0, MENU_ADD_SLIDE, 0, R.string.add_slide).setIcon(
    371                 R.drawable.ic_menu_add_slide);
    372 
    373         // Slide duration
    374         String duration = getResources().getString(R.string.duration_sec);
    375         menu.add(0, MENU_DURATION, 0,
    376                 duration.replace("%s", String.valueOf(slide.getDuration() / 1000))).setIcon(
    377                         R.drawable.ic_menu_duration);
    378 
    379         // Slide layout
    380         int resId;
    381         if (mSlideshowModel.getLayout().getLayoutType() == LayoutModel.LAYOUT_TOP_TEXT) {
    382             resId = R.string.layout_top;
    383         } else {
    384             resId = R.string.layout_bottom;
    385         }
    386         // FIXME: set correct icon when layout icon is available.
    387         menu.add(0, MENU_LAYOUT, 0, resId).setIcon(R.drawable.ic_menu_picture);
    388         return true;
    389     }
    390 
    391     @Override
    392     public boolean onOptionsItemSelected(MenuItem item) {
    393         switch (item.getItemId()) {
    394             case MENU_PREVIEW_SLIDESHOW:
    395                 previewSlideshow();
    396                 break;
    397 
    398             case MENU_REMOVE_TEXT:
    399                 SlideModel slide = mSlideshowModel.get(mPosition);
    400                 if (slide != null) {
    401                     slide.removeText();
    402                 }
    403                 break;
    404 
    405             case MENU_ADD_PICTURE:
    406                 Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
    407                 intent.setType(ContentType.IMAGE_UNSPECIFIED);
    408                 startActivityForResult(intent, REQUEST_CODE_CHANGE_PICTURE);
    409                 break;
    410 
    411             case MENU_TAKE_PICTURE:
    412                 intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    413                 startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE);
    414                 break;
    415 
    416             case MENU_DEL_PICTURE:
    417                 mSlideshowEditor.removeImage(mPosition);
    418                 setReplaceButtonText(R.string.add_picture);
    419                 break;
    420 
    421             case MENU_ADD_AUDIO:
    422                 MessageUtils.selectAudio(this, REQUEST_CODE_CHANGE_MUSIC);
    423                 break;
    424 
    425             case MENU_RECORD_SOUND:
    426                 MessageUtils.recordSound(this, REQUEST_CODE_RECORD_SOUND);
    427                 break;
    428 
    429             case MENU_DEL_AUDIO:
    430                 mSlideshowEditor.removeAudio(mPosition);
    431                 break;
    432 
    433             case MENU_ADD_VIDEO:
    434                 intent = new Intent(Intent.ACTION_GET_CONTENT);
    435                 intent.setType(ContentType.VIDEO_UNSPECIFIED);
    436                 startActivityForResult(intent, REQUEST_CODE_CHANGE_VIDEO);
    437                 break;
    438 
    439             case MENU_DEL_VIDEO:
    440                 mSlideshowEditor.removeVideo(mPosition);
    441                 break;
    442 
    443             case MENU_ADD_SLIDE:
    444                 mPosition++;
    445                 if ( mSlideshowEditor.addNewSlide(mPosition) ) {
    446                     // add successfully
    447                     showCurrentSlide();
    448                 } else {
    449                     // move position back
    450                     mPosition--;
    451                     Toast.makeText(this, R.string.cannot_add_slide_anymore,
    452                             Toast.LENGTH_SHORT).show();
    453                 }
    454                 break;
    455 
    456             case MENU_LAYOUT:
    457                 showLayoutSelectorDialog();
    458                 break;
    459 
    460             case MENU_DURATION:
    461                 showDurationDialog();
    462                 break;
    463         }
    464 
    465         return true;
    466     }
    467 
    468     private void setReplaceButtonText(int text) {
    469         mReplaceImage.setText(text);
    470     }
    471 
    472     private void showDurationDialog() {
    473         AlertDialog.Builder builder = new AlertDialog.Builder(this);
    474         builder.setIcon(R.drawable.ic_mms_duration);
    475         String title = getResources().getString(R.string.duration_selector_title);
    476         builder.setTitle(title + (mPosition + 1) + "/" + mSlideshowModel.size());
    477 
    478         builder.setItems(R.array.select_dialog_items,
    479                 new DialogInterface.OnClickListener() {
    480             public void onClick(DialogInterface dialog, int which) {
    481                 if ((which >= 0) && (which < NUM_DIRECT_DURATIONS)) {
    482                     mSlideshowEditor.changeDuration(
    483                             mPosition, (which + 1) * 1000);
    484                 } else {
    485                     Intent intent = new Intent(SlideEditorActivity.this,
    486                             EditSlideDurationActivity.class);
    487                     intent.putExtra(EditSlideDurationActivity.SLIDE_INDEX, mPosition);
    488                     intent.putExtra(EditSlideDurationActivity.SLIDE_TOTAL,
    489                             mSlideshowModel.size());
    490                     intent.putExtra(EditSlideDurationActivity.SLIDE_DUR,
    491                             mSlideshowModel.get(mPosition).getDuration() / 1000); // in seconds
    492                     startActivityForResult(intent, REQUEST_CODE_CHANGE_DURATION);
    493                 }
    494             }
    495         });
    496 
    497         builder.show();
    498     }
    499 
    500     private void showLayoutSelectorDialog() {
    501         AlertDialog.Builder builder = new AlertDialog.Builder(this);
    502         builder.setIcon(R.drawable.ic_mms_layout);
    503 
    504         String title = getResources().getString(R.string.layout_selector_title);
    505         builder.setTitle(title + (mPosition + 1) + "/" + mSlideshowModel.size());
    506 
    507         LayoutSelectorAdapter adapter = new LayoutSelectorAdapter(this);
    508         builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
    509             public void onClick(DialogInterface dialog, int which) {
    510                 switch (which) {
    511                     case 0: // Top text.
    512                         mSlideshowEditor.changeLayout(LayoutModel.LAYOUT_TOP_TEXT);
    513                         break;
    514                     case 1: // Bottom text.
    515                         mSlideshowEditor.changeLayout(LayoutModel.LAYOUT_BOTTOM_TEXT);
    516                         break;
    517                 }
    518             }
    519         });
    520 
    521         builder.show();
    522     }
    523 
    524     @Override
    525     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    526         if (resultCode != RESULT_OK) {
    527             return;
    528         }
    529 
    530         switch(requestCode) {
    531             case REQUEST_CODE_EDIT_TEXT:
    532                 // XXX where does this come from?  Action is probably not the
    533                 // right place to have the text...
    534                 mSlideshowEditor.changeText(mPosition, data.getAction());
    535                 break;
    536 
    537             case REQUEST_CODE_TAKE_PICTURE:
    538                 Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
    539                 if (bitmap == null) {
    540                     Toast.makeText(this,
    541                             getResourcesString(R.string.failed_to_add_media, getPictureString()),
    542                             Toast.LENGTH_SHORT).show();
    543                     return;
    544                 }
    545 
    546                 try {
    547                     mSlideshowEditor.changeImage(mPosition,
    548                             MessageUtils.saveBitmapAsPart(this, mUri, bitmap));
    549 
    550                     setReplaceButtonText(R.string.replace_image);
    551                 } catch (MmsException e) {
    552                     Log.e(TAG, "add image failed", e);
    553                     notifyUser("add picture failed");
    554                     Toast.makeText(SlideEditorActivity.this,
    555                             getResourcesString(R.string.failed_to_add_media, getPictureString()),
    556                             Toast.LENGTH_SHORT).show();
    557                 } catch (UnsupportContentTypeException e) {
    558                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    559                             getResourcesString(R.string.unsupported_media_format, getPictureString()),
    560                             getResourcesString(R.string.select_different_media, getPictureString()));
    561                 } catch (ResolutionException e) {
    562                     MessageUtils.resizeImageAsync(this, data.getData(), new Handler(),
    563                             mResizeImageCallback, false);
    564                 } catch (ExceedMessageSizeException e) {
    565                     MessageUtils.resizeImageAsync(this, data.getData(), new Handler(),
    566                             mResizeImageCallback, false);
    567                 }
    568                 break;
    569 
    570             case REQUEST_CODE_CHANGE_PICTURE:
    571                 try {
    572                     mSlideshowEditor.changeImage(mPosition, data.getData());
    573                     setReplaceButtonText(R.string.replace_image);
    574                 } catch (MmsException e) {
    575                     Log.e(TAG, "add image failed", e);
    576                     notifyUser("add picture failed");
    577                     Toast.makeText(SlideEditorActivity.this,
    578                             getResourcesString(R.string.failed_to_add_media, getPictureString()),
    579                             Toast.LENGTH_SHORT).show();
    580                 } catch (UnsupportContentTypeException e) {
    581                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    582                             getResourcesString(R.string.unsupported_media_format, getPictureString()),
    583                             getResourcesString(R.string.select_different_media, getPictureString()));
    584                 } catch (ResolutionException e) {
    585                     MessageUtils.resizeImageAsync(this, data.getData(), new Handler(),
    586                             mResizeImageCallback, false);
    587                 } catch (ExceedMessageSizeException e) {
    588                     MessageUtils.resizeImageAsync(this, data.getData(), new Handler(),
    589                             mResizeImageCallback, false);
    590                 }
    591                 break;
    592 
    593             case REQUEST_CODE_CHANGE_MUSIC:
    594             case REQUEST_CODE_RECORD_SOUND:
    595                 Uri uri;
    596                 if (requestCode == REQUEST_CODE_CHANGE_MUSIC) {
    597                     uri = (Uri) data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
    598                     if (Settings.System.DEFAULT_RINGTONE_URI.equals(uri)) {
    599                         return;
    600                     }
    601                 } else {
    602                     uri = data.getData();
    603                 }
    604 
    605                 try {
    606                     mSlideshowEditor.changeAudio(mPosition, uri);
    607                 } catch (MmsException e) {
    608                     Log.e(TAG, "add audio failed", e);
    609                     notifyUser("add music failed");
    610                     Toast.makeText(SlideEditorActivity.this,
    611                             getResourcesString(R.string.failed_to_add_media, getAudioString()),
    612                             Toast.LENGTH_SHORT).show();
    613                 } catch (UnsupportContentTypeException e) {
    614                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    615                             getResourcesString(R.string.unsupported_media_format, getAudioString()),
    616                             getResourcesString(R.string.select_different_media, getAudioString()));
    617                 } catch (ExceedMessageSizeException e) {
    618                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    619                             getResourcesString(R.string.exceed_message_size_limitation),
    620                             getResourcesString(R.string.failed_to_add_media, getAudioString()));
    621                 }
    622                 break;
    623 
    624             case REQUEST_CODE_CHANGE_VIDEO:
    625                 try {
    626                     mSlideshowEditor.changeVideo(mPosition, data.getData());
    627                 } catch (MmsException e) {
    628                     Log.e(TAG, "add video failed", e);
    629                     notifyUser("add video failed");
    630                     Toast.makeText(SlideEditorActivity.this,
    631                             getResourcesString(R.string.failed_to_add_media, getVideoString()),
    632                             Toast.LENGTH_SHORT).show();
    633                 } catch (UnsupportContentTypeException e) {
    634                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    635                             getResourcesString(R.string.unsupported_media_format, getVideoString()),
    636                             getResourcesString(R.string.select_different_media, getVideoString()));
    637                 } catch (ExceedMessageSizeException e) {
    638                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    639                             getResourcesString(R.string.exceed_message_size_limitation),
    640                             getResourcesString(R.string.failed_to_add_media, getVideoString()));
    641                 }
    642                 break;
    643 
    644             case REQUEST_CODE_CHANGE_DURATION:
    645                 mSlideshowEditor.changeDuration(mPosition,
    646                     Integer.valueOf(data.getAction()) * 1000);
    647                 break;
    648         }
    649     }
    650 
    651     private final ResizeImageResultCallback mResizeImageCallback = new ResizeImageResultCallback() {
    652         public void onResizeResult(PduPart part, boolean append) {
    653             Context context = SlideEditorActivity.this;
    654             if (part == null) {
    655                 Toast.makeText(SlideEditorActivity.this,
    656                         getResourcesString(R.string.failed_to_add_media, getPictureString()),
    657                         Toast.LENGTH_SHORT).show();
    658                 return;
    659             }
    660 
    661             try {
    662                 long messageId = ContentUris.parseId(mUri);
    663                 PduPersister persister = PduPersister.getPduPersister(context);
    664                 Uri newUri = persister.persistPart(part, messageId);
    665                 mSlideshowEditor.changeImage(mPosition, newUri);
    666 
    667                 setReplaceButtonText(R.string.replace_image);
    668             } catch (MmsException e) {
    669                 notifyUser("add picture failed");
    670                 Toast.makeText(SlideEditorActivity.this,
    671                         getResourcesString(R.string.failed_to_add_media, getPictureString()),
    672                         Toast.LENGTH_SHORT).show();
    673             } catch (UnsupportContentTypeException e) {
    674                 MessageUtils.showErrorDialog(SlideEditorActivity.this,
    675                         getResourcesString(R.string.unsupported_media_format, getPictureString()),
    676                         getResourcesString(R.string.select_different_media, getPictureString()));
    677             } catch (ResolutionException e) {
    678                 MessageUtils.showErrorDialog(SlideEditorActivity.this,
    679                         getResourcesString(R.string.failed_to_resize_image),
    680                         getResourcesString(R.string.resize_image_error_information));
    681             } catch (ExceedMessageSizeException e) {
    682                 MessageUtils.showErrorDialog(SlideEditorActivity.this,
    683                         getResourcesString(R.string.exceed_message_size_limitation),
    684                         getResourcesString(R.string.failed_to_add_media, getPictureString()));
    685             }
    686         }
    687     };
    688 
    689     private String getResourcesString(int id, String mediaName) {
    690         Resources r = getResources();
    691         return r.getString(id, mediaName);
    692     }
    693 
    694     private String getResourcesString(int id) {
    695         Resources r = getResources();
    696         return r.getString(id);
    697     }
    698 
    699     private String getAudioString() {
    700         return getResourcesString(R.string.type_audio);
    701     }
    702 
    703     private String getPictureString() {
    704         return getResourcesString(R.string.type_picture);
    705     }
    706 
    707     private String getVideoString() {
    708         return getResourcesString(R.string.type_video);
    709     }
    710 
    711     private void notifyUser(String message) {
    712         if (LOCAL_LOGV) {
    713             Log.v(TAG, "notifyUser: message=" + message);
    714         }
    715     }
    716 
    717     private void showCurrentSlide() {
    718         mPresenter.setLocation(mPosition);
    719         mPresenter.present();
    720         updateTitle();
    721 
    722         if (mSlideshowModel.get(mPosition).hasImage()) {
    723             setReplaceButtonText(R.string.replace_image);
    724         } else {
    725             setReplaceButtonText(R.string.add_picture);
    726         }
    727     }
    728 }
    729