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