| /* |
| * Copyright (C) 2008 Esmertec AG. |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.mms.ui; |
| |
| import android.app.ListActivity; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.util.Log; |
| import android.view.ContextMenu; |
| import android.view.ContextMenu.ContextMenuInfo; |
| import android.view.LayoutInflater; |
| import android.view.Menu; |
| import android.view.MenuItem; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.AdapterView; |
| import android.widget.AdapterView.AdapterContextMenuInfo; |
| import android.widget.ArrayAdapter; |
| import android.widget.ImageView; |
| import android.widget.ListView; |
| import android.widget.TextView; |
| import android.widget.Toast; |
| |
| import com.android.mms.R; |
| import com.android.mms.model.IModelChangedObserver; |
| import com.android.mms.model.Model; |
| import com.android.mms.model.SlideModel; |
| import com.android.mms.model.SlideshowModel; |
| import com.google.android.mms.MmsException; |
| import com.google.android.mms.pdu.PduBody; |
| import com.google.android.mms.pdu.PduPersister; |
| |
| /** |
| * A list of slides which allows user to edit each item in it. |
| */ |
| public class SlideshowEditActivity extends ListActivity { |
| private final static String TAG = "SlideshowEditActivity"; |
| private static final boolean DEBUG = false; |
| private static final boolean LOCAL_LOGV = false; |
| |
| // Menu ids. |
| private final static int MENU_MOVE_UP = 0; |
| private final static int MENU_MOVE_DOWN = 1; |
| private final static int MENU_REMOVE_SLIDE = 2; |
| private final static int MENU_ADD_SLIDE = 3; |
| private final static int MENU_DISCARD_SLIDESHOW = 4; |
| |
| private final static int REQUEST_CODE_EDIT_SLIDE = 6; |
| |
| // State. |
| private final static String STATE = "state"; |
| private final static String SLIDE_INDEX = "slide_index"; |
| private final static String MESSAGE_URI = "message_uri"; |
| |
| private ListView mList; |
| private SlideListAdapter mSlideListAdapter; |
| |
| private SlideshowModel mSlideshowModel = null; |
| private SlideshowEditor mSlideshowEditor = null; |
| |
| private Bundle mState; |
| private Uri mUri; |
| private Intent mResultIntent; |
| private boolean mDirty; |
| private View mAddSlideItem; |
| |
| @Override |
| protected void onCreate(Bundle icicle) { |
| super.onCreate(icicle); |
| |
| mList = getListView(); |
| mAddSlideItem = createAddSlideItem(); |
| mList.addFooterView(mAddSlideItem); |
| mAddSlideItem.setVisibility(View.GONE); |
| |
| if (icicle != null) { |
| // Retrieve previously saved state of this activity. |
| mState = icicle.getBundle(STATE); |
| } |
| |
| if (mState != null) { |
| mUri = Uri.parse(mState.getString(MESSAGE_URI)); |
| } else { |
| mUri = getIntent().getData(); |
| } |
| |
| if (mUri == null) { |
| Log.e(TAG, "Cannot startup activity, null Uri."); |
| finish(); |
| return; |
| } |
| |
| // Return the Uri of the message to whoever invoked us. |
| mResultIntent = new Intent(); |
| mResultIntent.setData(mUri); |
| |
| try { |
| initSlideList(); |
| adjustAddSlideVisibility(); |
| } catch (MmsException e) { |
| Log.e(TAG, "Failed to initialize the slide-list.", e); |
| finish(); |
| } |
| |
| registerForContextMenu(mList); |
| } |
| |
| private View createAddSlideItem() { |
| View v = ((LayoutInflater) getSystemService( |
| Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.slideshow_edit_item, null); |
| |
| // Add slide. |
| TextView text = (TextView) v.findViewById(R.id.slide_number_text); |
| text.setText(R.string.add_slide); |
| |
| text = (TextView) v.findViewById(R.id.text_preview); |
| text.setText(R.string.add_slide_hint); |
| text.setVisibility(View.VISIBLE); |
| |
| ImageView image = (ImageView) v.findViewById(R.id.image_preview); |
| image.setImageResource(R.drawable.ic_attach_slideshow_holo_light); |
| |
| return v; |
| } |
| |
| @Override |
| protected void onListItemClick(ListView l, View v, int position, long id) { |
| if (position == (l.getCount() - 1)) { |
| addNewSlide(); |
| } else { |
| openSlide(position); |
| } |
| } |
| |
| @Override |
| protected void onResume() { |
| super.onResume(); |
| |
| if (mState != null) { |
| mList.setSelection(mState.getInt(SLIDE_INDEX, 0)); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see android.app.Activity#onSaveInstanceState(android.os.Bundle) |
| */ |
| @Override |
| protected void onSaveInstanceState(Bundle outState) { |
| super.onSaveInstanceState(outState); |
| |
| mState = new Bundle(); |
| if (mList.getSelectedItemPosition() >= 0) { |
| mState.putInt(SLIDE_INDEX, mList.getSelectedItemPosition()); |
| } |
| |
| if (mUri != null) { |
| mState.putString(MESSAGE_URI, mUri.toString()); |
| } |
| |
| if (LOCAL_LOGV) { |
| Log.v(TAG, "Saving state: " + mState); |
| } |
| outState.putBundle(STATE, mState); |
| } |
| |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| |
| synchronized (this) { |
| if (mDirty) { |
| try { |
| PduBody pb = mSlideshowModel.toPduBody(); |
| PduPersister.getPduPersister(this).updateParts(mUri, pb, null); |
| mSlideshowModel.sync(pb); |
| } catch (MmsException e) { |
| Log.e(TAG, "Cannot update the message: " + mUri, e); |
| } |
| } |
| } |
| } |
| |
| @Override |
| protected void onDestroy() { |
| super.onDestroy(); |
| cleanupSlideshowModel(); |
| } |
| |
| private void cleanupSlideshowModel() { |
| if (mSlideshowModel != null) { |
| mSlideshowModel.unregisterModelChangedObserver( |
| mModelChangedObserver); |
| mSlideshowModel = null; |
| } |
| } |
| |
| private void initSlideList() throws MmsException { |
| cleanupSlideshowModel(); |
| mSlideshowModel = SlideshowModel.createFromMessageUri(this, mUri); |
| mSlideshowModel.registerModelChangedObserver(mModelChangedObserver); |
| mSlideshowEditor = new SlideshowEditor(this, mSlideshowModel); |
| mSlideListAdapter = new SlideListAdapter( |
| this, R.layout.slideshow_edit_item, mSlideshowModel); |
| mList.setAdapter(mSlideListAdapter); |
| } |
| |
| @Override |
| public boolean onPrepareOptionsMenu(Menu menu) { |
| menu.clear(); |
| |
| int position = mList.getSelectedItemPosition(); |
| if ((position >= 0) && (position != (mList.getCount() - 1))) { |
| // Selected one slide. |
| if (position > 0) { |
| menu.add(0, MENU_MOVE_UP, 0, R.string.move_up).setIcon(R.drawable.ic_menu_move_up); |
| } |
| |
| if (position < (mSlideListAdapter.getCount() - 1)) { |
| menu.add(0, MENU_MOVE_DOWN, 0, R.string.move_down).setIcon( |
| R.drawable.ic_menu_move_down); |
| } |
| |
| menu.add(0, MENU_ADD_SLIDE, 0, R.string.add_slide).setIcon(R.drawable.ic_menu_add_slide); |
| |
| menu.add(0, MENU_REMOVE_SLIDE, 0, R.string.remove_slide).setIcon( |
| android.R.drawable.ic_menu_delete); |
| } else { |
| menu.add(0, MENU_ADD_SLIDE, 0, R.string.add_slide).setIcon(R.drawable.ic_menu_add_slide); |
| } |
| |
| menu.add(0, MENU_DISCARD_SLIDESHOW, 0, |
| R.string.discard_slideshow).setIcon(R.drawable.ic_menu_delete_played); |
| |
| return true; |
| } |
| |
| @Override |
| public boolean onOptionsItemSelected(MenuItem item) { |
| int position = mList.getSelectedItemPosition(); |
| |
| switch (item.getItemId()) { |
| case MENU_MOVE_UP: |
| if ((position > 0) && (position < mSlideshowModel.size())) { |
| mSlideshowEditor.moveSlideUp(position); |
| mSlideListAdapter.notifyDataSetChanged(); |
| mList.setSelection(position - 1); |
| } |
| break; |
| case MENU_MOVE_DOWN: |
| if ((position >= 0) && (position < mSlideshowModel.size() - 1)) { |
| mSlideshowEditor.moveSlideDown(position); |
| mSlideListAdapter.notifyDataSetChanged(); |
| mList.setSelection(position + 1); |
| } |
| break; |
| case MENU_REMOVE_SLIDE: |
| if ((position >= 0) && (position < mSlideshowModel.size())) { |
| mSlideshowEditor.removeSlide(position); |
| mSlideListAdapter.notifyDataSetChanged(); |
| } |
| break; |
| case MENU_ADD_SLIDE: |
| addNewSlide(); |
| break; |
| case MENU_DISCARD_SLIDESHOW: |
| // delete all slides from slideshow. |
| mSlideshowEditor.removeAllSlides(); |
| mSlideListAdapter.notifyDataSetChanged(); |
| finish(); |
| break; |
| } |
| |
| return true; |
| } |
| |
| private void openSlide(int index) { |
| Intent intent = new Intent(this, SlideEditorActivity.class); |
| intent.setData(mUri); |
| intent.putExtra(SlideEditorActivity.SLIDE_INDEX, index); |
| startActivityForResult(intent, REQUEST_CODE_EDIT_SLIDE); |
| } |
| |
| private void adjustAddSlideVisibility() { |
| if (mSlideshowModel.size() >= SlideshowEditor.MAX_SLIDE_NUM) { |
| mAddSlideItem.setVisibility(View.GONE); |
| } else { |
| mAddSlideItem.setVisibility(View.VISIBLE); |
| } |
| } |
| |
| private void addNewSlide() { |
| if ( mSlideshowEditor.addNewSlide() ) { |
| // add successfully |
| mSlideListAdapter.notifyDataSetChanged(); |
| |
| // Select the new slide. |
| mList.requestFocus(); |
| mList.setSelection(mSlideshowModel.size() - 1); |
| } else { |
| Toast.makeText(this, R.string.cannot_add_slide_anymore, |
| Toast.LENGTH_SHORT).show(); |
| } |
| } |
| |
| @Override |
| protected void onActivityResult(int requestCode, int resultCode, |
| Intent data) { |
| if (resultCode != RESULT_OK) { |
| return; |
| } |
| |
| switch(requestCode) { |
| case REQUEST_CODE_EDIT_SLIDE: |
| synchronized (this) { |
| mDirty = true; |
| } |
| setResult(RESULT_OK, mResultIntent); |
| |
| if ((data != null) && data.getBooleanExtra("done", false)) { |
| finish(); |
| return; |
| } |
| |
| try { |
| initSlideList(); |
| adjustAddSlideVisibility(); |
| } catch (MmsException e) { |
| Log.e(TAG, "Failed to initialize the slide-list.", e); |
| finish(); |
| return; |
| } |
| break; |
| } |
| } |
| |
| private static class SlideListAdapter extends ArrayAdapter<SlideModel> { |
| private final Context mContext; |
| private final int mResource; |
| private final LayoutInflater mInflater; |
| private final SlideshowModel mSlideshow; |
| |
| public SlideListAdapter(Context context, int resource, |
| SlideshowModel slideshow) { |
| super(context, resource, slideshow); |
| |
| mContext = context; |
| mResource = resource; |
| mInflater = LayoutInflater.from(context); |
| mSlideshow = slideshow; |
| } |
| |
| @Override |
| public View getView(int position, View convertView, ViewGroup parent) { |
| return createViewFromResource(position, convertView, mResource); |
| } |
| |
| private View createViewFromResource(int position, View convertView, int resource) { |
| SlideListItemView slideListItemView; |
| slideListItemView = (SlideListItemView) mInflater.inflate( |
| resource, null); |
| |
| // Show slide number. |
| TextView text; |
| text = (TextView) slideListItemView.findViewById(R.id.slide_number_text); |
| text.setText(mContext.getString(R.string.slide_number, position + 1)); |
| |
| SlideModel slide = getItem(position); |
| int dur = slide.getDuration() / 1000; |
| text = (TextView) slideListItemView.findViewById(R.id.duration_text); |
| text.setText(mContext.getResources(). |
| getQuantityString(R.plurals.slide_duration, dur, dur)); |
| |
| Presenter presenter = PresenterFactory.getPresenter( |
| "SlideshowPresenter", mContext, slideListItemView, mSlideshow); |
| ((SlideshowPresenter) presenter).setLocation(position); |
| presenter.present(null); |
| |
| return slideListItemView; |
| } |
| } |
| |
| private final IModelChangedObserver mModelChangedObserver = |
| new IModelChangedObserver() { |
| public void onModelChanged(Model model, boolean dataChanged) { |
| synchronized (SlideshowEditActivity.this) { |
| mDirty = true; |
| } |
| setResult(RESULT_OK, mResultIntent); |
| adjustAddSlideVisibility(); |
| } |
| }; |
| |
| @Override |
| public void onCreateContextMenu(ContextMenu menu, View v, |
| ContextMenuInfo menuInfo) { |
| menu.setHeaderTitle(R.string.slideshow_options); |
| |
| AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; |
| int position = info.position; |
| |
| if ((position >= 0) && (position != (mList.getCount() - 1))) { |
| // Selected one slide. |
| if (position > 0) { |
| menu.add(0, MENU_MOVE_UP, 0, R.string.move_up).setIcon(R.drawable.ic_menu_move_up); |
| } |
| if (position < (mSlideListAdapter.getCount() - 1)) { |
| menu.add(0, MENU_MOVE_DOWN, 0, R.string.move_down).setIcon( |
| R.drawable.ic_menu_move_down); |
| } |
| |
| menu.add(0, MENU_ADD_SLIDE, 0, R.string.add_slide).setIcon( |
| R.drawable.ic_menu_add_slide); |
| |
| menu.add(0, MENU_REMOVE_SLIDE, 0, R.string.remove_slide).setIcon( |
| android.R.drawable.ic_menu_delete); |
| } |
| } |
| |
| @Override |
| public boolean onContextItemSelected(MenuItem item) { |
| AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); |
| int position = info.position; |
| |
| switch(item.getItemId()) { |
| case MENU_MOVE_UP: |
| if ((position > 0) && (position < mSlideshowModel.size())) { |
| mSlideshowEditor.moveSlideUp(position); |
| mSlideListAdapter.notifyDataSetChanged(); |
| mList.setSelection(position - 1); |
| } |
| break; |
| case MENU_MOVE_DOWN: |
| if ((position >= 0) && (position < mSlideshowModel.size() - 1)) { |
| mSlideshowEditor.moveSlideDown(position); |
| mSlideListAdapter.notifyDataSetChanged(); |
| mList.setSelection(position + 1); |
| } |
| break; |
| case MENU_REMOVE_SLIDE: |
| if ((position >= 0) && (position < mSlideshowModel.size())) { |
| mSlideshowEditor.removeSlide(position); |
| mSlideListAdapter.notifyDataSetChanged(); |
| } |
| break; |
| case MENU_ADD_SLIDE: |
| addNewSlide(); |
| break; |
| default: |
| break; |
| } |
| |
| return true; |
| } |
| } |