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