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