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.MmsException;
     21 import com.android.mms.R;
     22 import com.android.mms.model.IModelChangedObserver;
     23 import com.android.mms.model.Model;
     24 import com.android.mms.model.SlideModel;
     25 import com.android.mms.model.SlideshowModel;
     26 
     27 import com.google.android.mms.pdu.PduBody;
     28 import com.google.android.mms.pdu.PduPersister;
     29 
     30 import android.app.ListActivity;
     31 import android.content.Context;
     32 import android.content.Intent;
     33 import android.net.Uri;
     34 import android.os.Bundle;
     35 import android.util.Log;
     36 import android.view.LayoutInflater;
     37 import android.view.Menu;
     38 import android.view.MenuItem;
     39 import android.view.View;
     40 import android.view.ViewGroup;
     41 import android.widget.ArrayAdapter;
     42 import android.widget.ImageView;
     43 import android.widget.ListView;
     44 import android.widget.TextView;
     45 import android.widget.Toast;
     46 
     47 /**
     48  * A list of slides which allows user to edit each item in it.
     49  */
     50 public class SlideshowEditActivity extends ListActivity {
     51     private final static String TAG = "SlideshowEditActivity";
     52     private static final boolean DEBUG = false;
     53     private static final boolean LOCAL_LOGV = false;
     54 
     55     // Menu ids.
     56     private final static int MENU_MOVE_UP           = 0;
     57     private final static int MENU_MOVE_DOWN         = 1;
     58     private final static int MENU_REMOVE_SLIDE      = 2;
     59     private final static int MENU_ADD_SLIDE         = 3;
     60     private final static int MENU_DISCARD_SLIDESHOW = 4;
     61 
     62     private final static int REQUEST_CODE_EDIT_SLIDE         = 6;
     63 
     64     // State.
     65     private final static String STATE = "state";
     66     private final static String SLIDE_INDEX = "slide_index";
     67     private final static String MESSAGE_URI = "message_uri";
     68 
     69     private ListView mList;
     70     private SlideListAdapter mSlideListAdapter;
     71 
     72     private SlideshowModel mSlideshowModel = null;
     73     private SlideshowEditor mSlideshowEditor = null;
     74 
     75     private Bundle mState;
     76     private Uri mUri;
     77     private Intent mResultIntent;
     78     private boolean mDirty;
     79     private View mAddSlideItem;
     80 
     81     @Override
     82     protected void onCreate(Bundle icicle) {
     83         super.onCreate(icicle);
     84 
     85         mList = getListView();
     86         mAddSlideItem = createAddSlideItem();
     87         mList.addFooterView(mAddSlideItem);
     88         mAddSlideItem.setVisibility(View.GONE);
     89 
     90         if (icicle != null) {
     91             // Retrieve previously saved state of this activity.
     92             mState = icicle.getBundle(STATE);
     93         }
     94 
     95         if (mState != null) {
     96             mUri = Uri.parse(mState.getString(MESSAGE_URI));
     97         } else {
     98             mUri = getIntent().getData();
     99         }
    100 
    101         if (mUri == null) {
    102             Log.e(TAG, "Cannot startup activity, null Uri.");
    103             finish();
    104             return;
    105         }
    106 
    107         // Return the Uri of the message to whoever invoked us.
    108         mResultIntent = new Intent();
    109         mResultIntent.setData(mUri);
    110 
    111         try {
    112             initSlideList();
    113             adjustAddSlideVisibility();
    114         } catch (MmsException e) {
    115             Log.e(TAG, "Failed to initialize the slide-list.", e);
    116             finish();
    117         }
    118     }
    119 
    120     private View createAddSlideItem() {
    121         View v = ((LayoutInflater) getSystemService(
    122                 Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.slideshow_edit_item, null);
    123 
    124         //  Add slide.
    125         TextView text = (TextView) v.findViewById(R.id.slide_number_text);
    126         text.setText(R.string.add_slide);
    127 
    128         text = (TextView) v.findViewById(R.id.text_preview);
    129         text.setText(R.string.add_slide_hint);
    130         text.setVisibility(View.VISIBLE);
    131 
    132         ImageView image = (ImageView) v.findViewById(R.id.image_preview);
    133         image.setImageResource(R.drawable.ic_attach_slideshow_holo_light);
    134 
    135         return v;
    136     }
    137 
    138     @Override
    139     protected void onListItemClick(ListView l, View v, int position, long id) {
    140         if (position == (l.getCount() - 1)) {
    141             addNewSlide();
    142         } else {
    143             openSlide(position);
    144         }
    145     }
    146 
    147     @Override
    148     protected void onResume() {
    149         super.onResume();
    150 
    151         if (mState != null) {
    152             mList.setSelection(mState.getInt(SLIDE_INDEX, 0));
    153         }
    154     }
    155 
    156     /*
    157      * (non-Javadoc)
    158      * @see android.app.Activity#onSaveInstanceState(android.os.Bundle)
    159      */
    160     @Override
    161     protected void onSaveInstanceState(Bundle outState) {
    162         super.onSaveInstanceState(outState);
    163 
    164         mState = new Bundle();
    165         if (mList.getSelectedItemPosition() >= 0) {
    166             mState.putInt(SLIDE_INDEX, mList.getSelectedItemPosition());
    167         }
    168 
    169         if (mUri != null) {
    170             mState.putString(MESSAGE_URI, mUri.toString());
    171         }
    172 
    173         if (LOCAL_LOGV) {
    174             Log.v(TAG, "Saving state: " + mState);
    175         }
    176         outState.putBundle(STATE, mState);
    177     }
    178 
    179     @Override
    180     protected void onPause()  {
    181         super.onPause();
    182 
    183         synchronized (this) {
    184             if (mDirty) {
    185                 try {
    186                     PduBody pb = mSlideshowModel.toPduBody();
    187                     PduPersister.getPduPersister(this).updateParts(mUri, pb);
    188                     mSlideshowModel.sync(pb);
    189                 }  catch (MmsException e) {
    190                     Log.e(TAG, "Cannot update the message: " + mUri, e);
    191                 }
    192             }
    193         }
    194     }
    195 
    196     @Override
    197     protected void onDestroy() {
    198         super.onDestroy();
    199         cleanupSlideshowModel();
    200     }
    201 
    202     private void cleanupSlideshowModel() {
    203         if (mSlideshowModel != null) {
    204             mSlideshowModel.unregisterModelChangedObserver(
    205                     mModelChangedObserver);
    206             mSlideshowModel = null;
    207         }
    208     }
    209 
    210     private void initSlideList() throws MmsException {
    211         cleanupSlideshowModel();
    212         mSlideshowModel = SlideshowModel.createFromMessageUri(this, mUri);
    213         mSlideshowModel.registerModelChangedObserver(mModelChangedObserver);
    214         mSlideshowEditor = new SlideshowEditor(this, mSlideshowModel);
    215         mSlideListAdapter = new SlideListAdapter(
    216                 this, R.layout.slideshow_edit_item, mSlideshowModel);
    217         mList.setAdapter(mSlideListAdapter);
    218     }
    219 
    220     @Override
    221     public boolean onPrepareOptionsMenu(Menu menu) {
    222         menu.clear();
    223 
    224         int position = mList.getSelectedItemPosition();
    225         if ((position >= 0) && (position != (mList.getCount() - 1))) {
    226             // Selected one slide.
    227             if (position > 0) {
    228                 menu.add(0, MENU_MOVE_UP, 0, R.string.move_up).setIcon(R.drawable.ic_menu_move_up);
    229             }
    230 
    231             if (position < (mSlideListAdapter.getCount() - 1)) {
    232                 menu.add(0, MENU_MOVE_DOWN, 0, R.string.move_down).setIcon(
    233                         R.drawable.ic_menu_move_down);
    234             }
    235 
    236             menu.add(0, MENU_ADD_SLIDE, 0, R.string.add_slide).setIcon(R.drawable.ic_menu_add_slide);
    237 
    238             menu.add(0, MENU_REMOVE_SLIDE, 0, R.string.remove_slide).setIcon(
    239                     android.R.drawable.ic_menu_delete);
    240         } else {
    241             menu.add(0, MENU_ADD_SLIDE, 0, R.string.add_slide).setIcon(R.drawable.ic_menu_add_slide);
    242         }
    243 
    244         menu.add(0, MENU_DISCARD_SLIDESHOW, 0,
    245                 R.string.discard_slideshow).setIcon(R.drawable.ic_menu_delete_played);
    246 
    247         return true;
    248     }
    249 
    250     @Override
    251     public boolean onOptionsItemSelected(MenuItem item) {
    252         int position = mList.getSelectedItemPosition();
    253 
    254         switch (item.getItemId()) {
    255             case MENU_MOVE_UP:
    256                 if ((position > 0) && (position < mSlideshowModel.size())) {
    257                     mSlideshowEditor.moveSlideUp(position);
    258                     mSlideListAdapter.notifyDataSetChanged();
    259                     mList.setSelection(position - 1);
    260                 }
    261                 break;
    262             case MENU_MOVE_DOWN:
    263                 if ((position >= 0) && (position < mSlideshowModel.size() - 1)) {
    264                     mSlideshowEditor.moveSlideDown(position);
    265                     mSlideListAdapter.notifyDataSetChanged();
    266                     mList.setSelection(position + 1);
    267                 }
    268                 break;
    269             case MENU_REMOVE_SLIDE:
    270                 if ((position >= 0) && (position < mSlideshowModel.size())) {
    271                     mSlideshowEditor.removeSlide(position);
    272                     mSlideListAdapter.notifyDataSetChanged();
    273                 }
    274                 break;
    275             case MENU_ADD_SLIDE:
    276                 addNewSlide();
    277                 break;
    278             case MENU_DISCARD_SLIDESHOW:
    279                 // delete all slides from slideshow.
    280                 mSlideshowEditor.removeAllSlides();
    281                 mSlideListAdapter.notifyDataSetChanged();
    282                 finish();
    283                 break;
    284         }
    285 
    286         return true;
    287     }
    288 
    289     private void openSlide(int index) {
    290         Intent intent = new Intent(this, SlideEditorActivity.class);
    291         intent.setData(mUri);
    292         intent.putExtra(SlideEditorActivity.SLIDE_INDEX, index);
    293         startActivityForResult(intent, REQUEST_CODE_EDIT_SLIDE);
    294     }
    295 
    296     private void adjustAddSlideVisibility() {
    297         if (mSlideshowModel.size() >= SlideshowEditor.MAX_SLIDE_NUM) {
    298             mAddSlideItem.setVisibility(View.GONE);
    299         } else {
    300             mAddSlideItem.setVisibility(View.VISIBLE);
    301         }
    302     }
    303 
    304     private void addNewSlide() {
    305         if ( mSlideshowEditor.addNewSlide() ) {
    306             // add successfully
    307             mSlideListAdapter.notifyDataSetChanged();
    308 
    309             // Select the new slide.
    310             mList.requestFocus();
    311             mList.setSelection(mSlideshowModel.size() - 1);
    312         } else {
    313             Toast.makeText(this, R.string.cannot_add_slide_anymore,
    314                     Toast.LENGTH_SHORT).show();
    315         }
    316     }
    317 
    318     @Override
    319     protected void onActivityResult(int requestCode, int resultCode,
    320             Intent data) {
    321         if (resultCode != RESULT_OK) {
    322             return;
    323         }
    324 
    325         switch(requestCode) {
    326             case REQUEST_CODE_EDIT_SLIDE:
    327                 synchronized (this) {
    328                     mDirty = true;
    329                 }
    330                 setResult(RESULT_OK, mResultIntent);
    331 
    332                 if ((data != null) && data.getBooleanExtra("done", false)) {
    333                     finish();
    334                     return;
    335                 }
    336 
    337                 try {
    338                     initSlideList();
    339                 } catch (MmsException e) {
    340                     Log.e(TAG, "Failed to initialize the slide-list.", e);
    341                     finish();
    342                     return;
    343                 }
    344                 break;
    345         }
    346     }
    347 
    348     private static class SlideListAdapter extends ArrayAdapter<SlideModel> {
    349         private final Context mContext;
    350         private final int mResource;
    351         private final LayoutInflater mInflater;
    352         private final SlideshowModel mSlideshow;
    353 
    354         public SlideListAdapter(Context context, int resource,
    355                 SlideshowModel slideshow) {
    356             super(context, resource, slideshow);
    357 
    358             mContext = context;
    359             mResource = resource;
    360             mInflater = LayoutInflater.from(context);
    361             mSlideshow = slideshow;
    362         }
    363 
    364         @Override
    365         public View getView(int position, View convertView, ViewGroup parent) {
    366             return createViewFromResource(position, convertView, mResource);
    367         }
    368 
    369         private View createViewFromResource(int position, View convertView, int resource) {
    370             SlideListItemView slideListItemView;
    371             slideListItemView = (SlideListItemView) mInflater.inflate(
    372                     resource, null);
    373 
    374             // Show slide number.
    375             TextView text;
    376             text = (TextView) slideListItemView.findViewById(R.id.slide_number_text);
    377             text.setText(mContext.getString(R.string.slide_number, position + 1));
    378 
    379             SlideModel slide = getItem(position);
    380             int dur = slide.getDuration() / 1000;
    381             text = (TextView) slideListItemView.findViewById(R.id.duration_text);
    382             text.setText(mContext.getResources().
    383                          getQuantityString(R.plurals.slide_duration, dur, dur));
    384 
    385             Presenter presenter = PresenterFactory.getPresenter(
    386                     "SlideshowPresenter", mContext, slideListItemView, mSlideshow);
    387             ((SlideshowPresenter) presenter).setLocation(position);
    388             presenter.present();
    389 
    390             return slideListItemView;
    391         }
    392     }
    393 
    394     private final IModelChangedObserver mModelChangedObserver =
    395         new IModelChangedObserver() {
    396             public void onModelChanged(Model model, boolean dataChanged) {
    397                 synchronized (SlideshowEditActivity.this) {
    398                     mDirty = true;
    399                 }
    400                 setResult(RESULT_OK, mResultIntent);
    401                 adjustAddSlideVisibility();
    402             }
    403         };
    404 }
    405