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