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