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