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