SlideshowEditActivity.java revision 51e4621fa12400b1e79cc18b7bb0f9a83af6b622
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 com.google.android.mms.MmsException;
21import com.android.mms.R;
22import com.android.mms.model.IModelChangedObserver;
23import com.android.mms.model.Model;
24import com.android.mms.model.SlideModel;
25import com.android.mms.model.SlideshowModel;
26
27import com.google.android.mms.pdu.PduBody;
28import com.google.android.mms.pdu.PduPersister;
29
30import android.app.ListActivity;
31import android.content.Context;
32import android.content.Intent;
33import android.net.Uri;
34import android.os.Bundle;
35import android.util.Log;
36import android.view.LayoutInflater;
37import android.view.Menu;
38import android.view.MenuItem;
39import android.view.View;
40import android.view.ViewGroup;
41import android.widget.ArrayAdapter;
42import android.widget.ImageView;
43import android.widget.ListView;
44import android.widget.TextView;
45import android.widget.Toast;
46
47/**
48 * A list of slides which allows user to edit each item in it.
49 */
50public 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(null);
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