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                 dialog.dismiss();
    495             }
    496         });
    497 
    498         builder.show();
    499     }
    500 
    501     private void showLayoutSelectorDialog() {
    502         AlertDialog.Builder builder = new AlertDialog.Builder(this);
    503         builder.setIcon(R.drawable.ic_mms_layout);
    504 
    505         String title = getResources().getString(R.string.layout_selector_title);
    506         builder.setTitle(title + (mPosition + 1) + "/" + mSlideshowModel.size());
    507 
    508         LayoutSelectorAdapter adapter = new LayoutSelectorAdapter(this);
    509         builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
    510             public void onClick(DialogInterface dialog, int which) {
    511                 switch (which) {
    512                     case 0: // Top text.
    513                         mSlideshowEditor.changeLayout(LayoutModel.LAYOUT_TOP_TEXT);
    514                         break;
    515                     case 1: // Bottom text.
    516                         mSlideshowEditor.changeLayout(LayoutModel.LAYOUT_BOTTOM_TEXT);
    517                         break;
    518                 }
    519                 dialog.dismiss();
    520             }
    521         });
    522 
    523         builder.show();
    524     }
    525 
    526     @Override
    527     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    528         if (resultCode != RESULT_OK) {
    529             return;
    530         }
    531 
    532         switch(requestCode) {
    533             case REQUEST_CODE_EDIT_TEXT:
    534                 // XXX where does this come from?  Action is probably not the
    535                 // right place to have the text...
    536                 mSlideshowEditor.changeText(mPosition, data.getAction());
    537                 break;
    538 
    539             case REQUEST_CODE_TAKE_PICTURE:
    540                 Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");
    541                 if (bitmap == null) {
    542                     Toast.makeText(this,
    543                             getResourcesString(R.string.failed_to_add_media, getPictureString()),
    544                             Toast.LENGTH_SHORT).show();
    545                     return;
    546                 }
    547 
    548                 try {
    549                     mSlideshowEditor.changeImage(mPosition,
    550                             MessageUtils.saveBitmapAsPart(this, mUri, bitmap));
    551 
    552                     setReplaceButtonText(R.string.replace_image);
    553                 } catch (MmsException e) {
    554                     Log.e(TAG, "add image failed", e);
    555                     notifyUser("add picture failed");
    556                     Toast.makeText(SlideEditorActivity.this,
    557                             getResourcesString(R.string.failed_to_add_media, getPictureString()),
    558                             Toast.LENGTH_SHORT).show();
    559                 } catch (UnsupportContentTypeException e) {
    560                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    561                             getResourcesString(R.string.unsupported_media_format, getPictureString()),
    562                             getResourcesString(R.string.select_different_media, getPictureString()));
    563                 } catch (ResolutionException e) {
    564                     MessageUtils.resizeImageAsync(this, data.getData(), new Handler(),
    565                             mResizeImageCallback, false);
    566                 } catch (ExceedMessageSizeException e) {
    567                     MessageUtils.resizeImageAsync(this, data.getData(), new Handler(),
    568                             mResizeImageCallback, false);
    569                 }
    570                 break;
    571 
    572             case REQUEST_CODE_CHANGE_PICTURE:
    573                 try {
    574                     mSlideshowEditor.changeImage(mPosition, data.getData());
    575                     setReplaceButtonText(R.string.replace_image);
    576                 } catch (MmsException e) {
    577                     Log.e(TAG, "add image failed", e);
    578                     notifyUser("add picture failed");
    579                     Toast.makeText(SlideEditorActivity.this,
    580                             getResourcesString(R.string.failed_to_add_media, getPictureString()),
    581                             Toast.LENGTH_SHORT).show();
    582                 } catch (UnsupportContentTypeException e) {
    583                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    584                             getResourcesString(R.string.unsupported_media_format, getPictureString()),
    585                             getResourcesString(R.string.select_different_media, getPictureString()));
    586                 } catch (ResolutionException e) {
    587                     MessageUtils.resizeImageAsync(this, data.getData(), new Handler(),
    588                             mResizeImageCallback, false);
    589                 } catch (ExceedMessageSizeException e) {
    590                     MessageUtils.resizeImageAsync(this, data.getData(), new Handler(),
    591                             mResizeImageCallback, false);
    592                 }
    593                 break;
    594 
    595             case REQUEST_CODE_CHANGE_MUSIC:
    596             case REQUEST_CODE_RECORD_SOUND:
    597                 Uri uri;
    598                 if (requestCode == REQUEST_CODE_CHANGE_MUSIC) {
    599                     uri = (Uri) data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
    600                     if (Settings.System.DEFAULT_RINGTONE_URI.equals(uri)) {
    601                         return;
    602                     }
    603                 } else {
    604                     uri = data.getData();
    605                 }
    606 
    607                 try {
    608                     mSlideshowEditor.changeAudio(mPosition, uri);
    609                 } catch (MmsException e) {
    610                     Log.e(TAG, "add audio failed", e);
    611                     notifyUser("add music failed");
    612                     Toast.makeText(SlideEditorActivity.this,
    613                             getResourcesString(R.string.failed_to_add_media, getAudioString()),
    614                             Toast.LENGTH_SHORT).show();
    615                 } catch (UnsupportContentTypeException e) {
    616                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    617                             getResourcesString(R.string.unsupported_media_format, getAudioString()),
    618                             getResourcesString(R.string.select_different_media, getAudioString()));
    619                 } catch (ExceedMessageSizeException e) {
    620                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    621                             getResourcesString(R.string.exceed_message_size_limitation),
    622                             getResourcesString(R.string.failed_to_add_media, getAudioString()));
    623                 }
    624                 break;
    625 
    626             case REQUEST_CODE_CHANGE_VIDEO:
    627                 try {
    628                     mSlideshowEditor.changeVideo(mPosition, data.getData());
    629                 } catch (MmsException e) {
    630                     Log.e(TAG, "add video failed", e);
    631                     notifyUser("add video failed");
    632                     Toast.makeText(SlideEditorActivity.this,
    633                             getResourcesString(R.string.failed_to_add_media, getVideoString()),
    634                             Toast.LENGTH_SHORT).show();
    635                 } catch (UnsupportContentTypeException e) {
    636                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    637                             getResourcesString(R.string.unsupported_media_format, getVideoString()),
    638                             getResourcesString(R.string.select_different_media, getVideoString()));
    639                 } catch (ExceedMessageSizeException e) {
    640                     MessageUtils.showErrorDialog(SlideEditorActivity.this,
    641                             getResourcesString(R.string.exceed_message_size_limitation),
    642                             getResourcesString(R.string.failed_to_add_media, getVideoString()));
    643                 }
    644                 break;
    645 
    646             case REQUEST_CODE_CHANGE_DURATION:
    647                 mSlideshowEditor.changeDuration(mPosition,
    648                     Integer.valueOf(data.getAction()) * 1000);
    649                 break;
    650         }
    651     }
    652 
    653     private final ResizeImageResultCallback mResizeImageCallback = new ResizeImageResultCallback() {
    654         public void onResizeResult(PduPart part, boolean append) {
    655             Context context = SlideEditorActivity.this;
    656             if (part == null) {
    657                 Toast.makeText(SlideEditorActivity.this,
    658                         getResourcesString(R.string.failed_to_add_media, getPictureString()),
    659                         Toast.LENGTH_SHORT).show();
    660                 return;
    661             }
    662 
    663             try {
    664                 long messageId = ContentUris.parseId(mUri);
    665                 PduPersister persister = PduPersister.getPduPersister(context);
    666                 Uri newUri = persister.persistPart(part, messageId);
    667                 mSlideshowEditor.changeImage(mPosition, newUri);
    668 
    669                 setReplaceButtonText(R.string.replace_image);
    670             } catch (MmsException e) {
    671                 notifyUser("add picture failed");
    672                 Toast.makeText(SlideEditorActivity.this,
    673                         getResourcesString(R.string.failed_to_add_media, getPictureString()),
    674                         Toast.LENGTH_SHORT).show();
    675             } catch (UnsupportContentTypeException e) {
    676                 MessageUtils.showErrorDialog(SlideEditorActivity.this,
    677                         getResourcesString(R.string.unsupported_media_format, getPictureString()),
    678                         getResourcesString(R.string.select_different_media, getPictureString()));
    679             } catch (ResolutionException e) {
    680                 MessageUtils.showErrorDialog(SlideEditorActivity.this,
    681                         getResourcesString(R.string.failed_to_resize_image),
    682                         getResourcesString(R.string.resize_image_error_information));
    683             } catch (ExceedMessageSizeException e) {
    684                 MessageUtils.showErrorDialog(SlideEditorActivity.this,
    685                         getResourcesString(R.string.exceed_message_size_limitation),
    686                         getResourcesString(R.string.failed_to_add_media, getPictureString()));
    687             }
    688         }
    689     };
    690 
    691     private String getResourcesString(int id, String mediaName) {
    692         Resources r = getResources();
    693         return r.getString(id, mediaName);
    694     }
    695 
    696     private String getResourcesString(int id) {
    697         Resources r = getResources();
    698         return r.getString(id);
    699     }
    700 
    701     private String getAudioString() {
    702         return getResourcesString(R.string.type_audio);
    703     }
    704 
    705     private String getPictureString() {
    706         return getResourcesString(R.string.type_picture);
    707     }
    708 
    709     private String getVideoString() {
    710         return getResourcesString(R.string.type_video);
    711     }
    712 
    713     private void notifyUser(String message) {
    714         if (LOCAL_LOGV) {
    715             Log.v(TAG, "notifyUser: message=" + message);
    716         }
    717     }
    718 
    719     private void showCurrentSlide() {
    720         mPresenter.setLocation(mPosition);
    721         mPresenter.present();
    722         updateTitle();
    723 
    724         if (mSlideshowModel.get(mPosition).hasImage()) {
    725             setReplaceButtonText(R.string.replace_image);
    726         } else {
    727             setReplaceButtonText(R.string.add_picture);
    728         }
    729     }
    730 }
    731