• 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.model;
19 
20 import com.android.mms.ContentRestrictionException;
21 import com.android.mms.dom.smil.SmilParElementImpl;
22 
23 import org.w3c.dom.events.Event;
24 import org.w3c.dom.events.EventListener;
25 import org.w3c.dom.smil.ElementTime;
26 
27 import android.util.Config;
28 import android.util.Log;
29 
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.ListIterator;
35 
36 public class SlideModel extends Model
37         implements List<MediaModel>, EventListener {
38     private static final String TAG = "SlideModel";
39     private static final boolean DEBUG = false;
40     private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
41     private static final int DEFAULT_SLIDE_DURATION = 5000;
42 
43     private final ArrayList<MediaModel> mMedia = new ArrayList<MediaModel>();
44 
45     private MediaModel mText;
46     private MediaModel mImage;
47     private MediaModel mAudio;
48     private MediaModel mVideo;
49 
50     private boolean mCanAddImage = true;
51     private boolean mCanAddAudio = true;
52     private boolean mCanAddVideo = true;
53 
54     private int mDuration;
55     private boolean mVisible = true;
56     private short mFill;
57     private int mSlideSize;
58     private SlideshowModel mParent;
59 
SlideModel(SlideshowModel slideshow)60     public SlideModel(SlideshowModel slideshow) {
61         this(DEFAULT_SLIDE_DURATION, slideshow);
62     }
63 
SlideModel(int duration, SlideshowModel slideshow)64     public SlideModel(int duration, SlideshowModel slideshow) {
65         mDuration = duration;
66         mParent = slideshow;
67     }
68 
69     /**
70      * Create a SlideModel with exist media collection.
71      *
72      * @param duration The duration of the slide.
73      * @param mediaList The exist media collection.
74      *
75      * @throws IllegalStateException One or more media in the mediaList cannot
76      *         be added into the slide due to a slide cannot contain image
77      *         and video or audio and video at the same time.
78      */
SlideModel(int duration, ArrayList<MediaModel> mediaList)79     public SlideModel(int duration, ArrayList<MediaModel> mediaList) {
80         mDuration = duration;
81 
82         int maxDur = 0;
83         for (MediaModel media : mediaList) {
84             internalAdd(media);
85 
86             int mediaDur = media.getDuration();
87             if (mediaDur > maxDur) {
88                 maxDur = mediaDur;
89             }
90         }
91 
92         updateDuration(maxDur);
93     }
94 
internalAdd(MediaModel media)95     private void internalAdd(MediaModel media) throws IllegalStateException {
96         if (media == null) {
97             // Don't add null value into the list.
98             return;
99         }
100 
101         if (media.isText()) {
102             internalAddOrReplace(mText, media);
103             mText = media;
104         } else if (media.isImage()) {
105             if (mCanAddImage) {
106                 internalAddOrReplace(mImage, media);
107                 mImage = media;
108                 mCanAddVideo = false;
109             } else {
110                 throw new IllegalStateException();
111             }
112         } else if (media.isAudio()) {
113             if (mCanAddAudio) {
114                 internalAddOrReplace(mAudio, media);
115                 mAudio = media;
116                 mCanAddVideo = false;
117             } else {
118                 throw new IllegalStateException();
119             }
120         } else if (media.isVideo()) {
121             if (mCanAddVideo) {
122                 internalAddOrReplace(mVideo, media);
123                 mVideo = media;
124                 mCanAddImage = false;
125                 mCanAddAudio = false;
126             } else {
127                 throw new IllegalStateException();
128             }
129         }
130     }
131 
internalAddOrReplace(MediaModel old, MediaModel media)132     private void internalAddOrReplace(MediaModel old, MediaModel media) {
133         int addSize = media.getMediaSize();
134         int removeSize;
135         if (old == null) {
136             if (null != mParent) {
137                 mParent.checkMessageSize(addSize);
138             }
139             mMedia.add(media);
140             increaseSlideSize(addSize);
141             increaseMessageSize(addSize);
142         } else {
143             removeSize = old.getMediaSize();
144             if (addSize > removeSize) {
145                 if (null != mParent) {
146                     mParent.checkMessageSize(addSize - removeSize);
147                 }
148                 increaseSlideSize(addSize - removeSize);
149                 increaseMessageSize(addSize - removeSize);
150             } else {
151                 decreaseSlideSize(removeSize - addSize);
152                 decreaseMessageSize(removeSize - addSize);
153             }
154             mMedia.set(mMedia.indexOf(old), media);
155             old.unregisterAllModelChangedObservers();
156         }
157 
158         for (IModelChangedObserver observer : mModelChangedObservers) {
159             media.registerModelChangedObserver(observer);
160         }
161     }
162 
internalRemove(Object object)163     private boolean internalRemove(Object object) {
164         if (mMedia.remove(object)) {
165             if (object instanceof TextModel) {
166                 mText = null;
167             } else if (object instanceof ImageModel) {
168                 mImage = null;
169                 mCanAddVideo = true;
170             } else if (object instanceof AudioModel) {
171                 mAudio = null;
172                 mCanAddVideo = true;
173             } else if (object instanceof VideoModel) {
174                 mVideo = null;
175                 mCanAddImage = true;
176                 mCanAddAudio = true;
177             }
178             int decreaseSize = ((MediaModel) object).getMediaSize();
179             decreaseSlideSize(decreaseSize);
180             decreaseMessageSize(decreaseSize);
181 
182             ((Model) object).unregisterAllModelChangedObservers();
183 
184             return true;
185         }
186 
187         return false;
188     }
189 
190     /**
191      * @return the mDuration
192      */
getDuration()193     public int getDuration() {
194         return mDuration;
195     }
196 
197     /**
198      * @param duration the mDuration to set
199      */
setDuration(int duration)200     public void setDuration(int duration) {
201         mDuration = duration;
202         notifyModelChanged(true);
203     }
204 
getSlideSize()205     public int getSlideSize() {
206         return mSlideSize;
207     }
208 
increaseSlideSize(int increaseSize)209     public void increaseSlideSize(int increaseSize) {
210         if (increaseSize > 0) {
211             mSlideSize += increaseSize;
212         }
213     }
214 
decreaseSlideSize(int decreaseSize)215     public void decreaseSlideSize(int decreaseSize) {
216         if (decreaseSize > 0) {
217             mSlideSize -= decreaseSize;
218         }
219     }
220 
setParent(SlideshowModel parent)221     public void setParent(SlideshowModel parent) {
222         mParent = parent;
223     }
224 
increaseMessageSize(int increaseSize)225     public void increaseMessageSize(int increaseSize) {
226         if ((increaseSize > 0) && (null != mParent)) {
227             int size = mParent.getCurrentMessageSize();
228             size += increaseSize;
229             mParent.setCurrentMessageSize(size);
230         }
231     }
232 
decreaseMessageSize(int decreaseSize)233     public void decreaseMessageSize(int decreaseSize) {
234         if ((decreaseSize > 0) && (null != mParent)) {
235             int size = mParent.getCurrentMessageSize();
236             size -= decreaseSize;
237             mParent.setCurrentMessageSize(size);
238         }
239     }
240 
241     //
242     // Implement List<E> interface.
243     //
244 
245     /**
246      * Add a MediaModel to the slide. If the slide has already contained
247      * a media object in the same type, the media object will be replaced by
248      * the new one.
249      *
250      * @param object A media object to be added into the slide.
251      * @return true
252      * @throws IllegalStateException One or more media in the mediaList cannot
253      *         be added into the slide due to a slide cannot contain image
254      *         and video or audio and video at the same time.
255      * @throws ContentRestrictionException when can not add this object.
256      *
257      */
add(MediaModel object)258     public boolean add(MediaModel object) {
259         internalAdd(object);
260         notifyModelChanged(true);
261         return true;
262     }
263 
addAll(Collection<? extends MediaModel> collection)264     public boolean addAll(Collection<? extends MediaModel> collection) {
265         throw new UnsupportedOperationException("Operation not supported.");
266     }
267 
clear()268     public void clear() {
269         if (mMedia.size() > 0) {
270             for (MediaModel media : mMedia) {
271                 media.unregisterAllModelChangedObservers();
272                 int decreaseSize = media.getMediaSize();
273                 decreaseSlideSize(decreaseSize);
274                 decreaseMessageSize(decreaseSize);
275             }
276             mMedia.clear();
277 
278             mText = null;
279             mImage = null;
280             mAudio = null;
281             mVideo = null;
282 
283             mCanAddImage = true;
284             mCanAddAudio = true;
285             mCanAddVideo = true;
286 
287             notifyModelChanged(true);
288         }
289     }
290 
contains(Object object)291     public boolean contains(Object object) {
292         return mMedia.contains(object);
293     }
294 
containsAll(Collection<?> collection)295     public boolean containsAll(Collection<?> collection) {
296         return mMedia.containsAll(collection);
297     }
298 
isEmpty()299     public boolean isEmpty() {
300         return mMedia.isEmpty();
301     }
302 
iterator()303     public Iterator<MediaModel> iterator() {
304         return mMedia.iterator();
305     }
306 
remove(Object object)307     public boolean remove(Object object) {
308         if ((object != null) && (object instanceof MediaModel)
309                 && internalRemove(object)) {
310             notifyModelChanged(true);
311             return true;
312         }
313         return false;
314     }
315 
removeAll(Collection<?> collection)316     public boolean removeAll(Collection<?> collection) {
317         throw new UnsupportedOperationException("Operation not supported.");
318     }
319 
retainAll(Collection<?> collection)320     public boolean retainAll(Collection<?> collection) {
321         throw new UnsupportedOperationException("Operation not supported.");
322     }
323 
size()324     public int size() {
325         return mMedia.size();
326     }
327 
toArray()328     public Object[] toArray() {
329         return mMedia.toArray();
330     }
331 
toArray(T[] array)332     public <T> T[] toArray(T[] array) {
333         return mMedia.toArray(array);
334     }
335 
add(int location, MediaModel object)336     public void add(int location, MediaModel object) {
337         throw new UnsupportedOperationException("Operation not supported.");
338     }
339 
addAll(int location, Collection<? extends MediaModel> collection)340     public boolean addAll(int location,
341             Collection<? extends MediaModel> collection) {
342         throw new UnsupportedOperationException("Operation not supported.");
343     }
344 
get(int location)345     public MediaModel get(int location) {
346         return mMedia.get(location);
347     }
348 
indexOf(Object object)349     public int indexOf(Object object) {
350         return mMedia.indexOf(object);
351     }
352 
lastIndexOf(Object object)353     public int lastIndexOf(Object object) {
354         return mMedia.lastIndexOf(object);
355     }
356 
listIterator()357     public ListIterator<MediaModel> listIterator() {
358         return mMedia.listIterator();
359     }
360 
listIterator(int location)361     public ListIterator<MediaModel> listIterator(int location) {
362         return mMedia.listIterator(location);
363     }
364 
remove(int location)365     public MediaModel remove(int location) {
366         MediaModel media = mMedia.get(location);
367         if ((media != null) && internalRemove(media)) {
368             notifyModelChanged(true);
369         }
370         return media;
371     }
372 
set(int location, MediaModel object)373     public MediaModel set(int location, MediaModel object) {
374         throw new UnsupportedOperationException("Operation not supported.");
375     }
376 
subList(int start, int end)377     public List<MediaModel> subList(int start, int end) {
378         return mMedia.subList(start, end);
379     }
380 
381     /**
382      * @return the mVisible
383      */
isVisible()384     public boolean isVisible() {
385         return mVisible;
386     }
387 
388     /**
389      * @param visible the mVisible to set
390      */
setVisible(boolean visible)391     public void setVisible(boolean visible) {
392         mVisible = visible;
393         notifyModelChanged(true);
394     }
395 
396     /**
397      * @return the mFill
398      */
getFill()399     public short getFill() {
400         return mFill;
401     }
402 
403     /**
404      * @param fill the mFill to set
405      */
setFill(short fill)406     public void setFill(short fill) {
407         mFill = fill;
408         notifyModelChanged(true);
409     }
410 
411     @Override
registerModelChangedObserverInDescendants( IModelChangedObserver observer)412     protected void registerModelChangedObserverInDescendants(
413             IModelChangedObserver observer) {
414         for (MediaModel media : mMedia) {
415             media.registerModelChangedObserver(observer);
416         }
417     }
418 
419     @Override
unregisterModelChangedObserverInDescendants( IModelChangedObserver observer)420     protected void unregisterModelChangedObserverInDescendants(
421             IModelChangedObserver observer) {
422         for (MediaModel media : mMedia) {
423             media.unregisterModelChangedObserver(observer);
424         }
425     }
426 
427     @Override
unregisterAllModelChangedObserversInDescendants()428     protected void unregisterAllModelChangedObserversInDescendants() {
429         for (MediaModel media : mMedia) {
430             media.unregisterAllModelChangedObservers();
431         }
432     }
433 
434     // EventListener Interface
handleEvent(Event evt)435     public void handleEvent(Event evt) {
436         if (evt.getType().equals(SmilParElementImpl.SMIL_SLIDE_START_EVENT)) {
437             if (LOCAL_LOGV) {
438                 Log.v(TAG, "Start to play slide: " + this);
439             }
440             mVisible = true;
441         } else if (mFill != ElementTime.FILL_FREEZE) {
442             if (LOCAL_LOGV) {
443                 Log.v(TAG, "Stop playing slide: " + this);
444             }
445             mVisible = false;
446         }
447 
448         notifyModelChanged(false);
449     }
450 
hasText()451     public boolean hasText() {
452         return mText != null;
453     }
454 
hasImage()455     public boolean hasImage() {
456         return mImage != null;
457     }
458 
hasAudio()459     public boolean hasAudio() {
460         return mAudio != null;
461     }
462 
hasVideo()463     public boolean hasVideo() {
464         return mVideo != null;
465     }
466 
removeText()467     public boolean removeText() {
468         return remove(mText);
469     }
470 
removeImage()471     public boolean removeImage() {
472         return remove(mImage);
473     }
474 
removeAudio()475     public boolean removeAudio() {
476         return remove(mAudio);
477     }
478 
removeVideo()479     public boolean removeVideo() {
480         return remove(mVideo);
481     }
482 
getText()483     public TextModel getText() {
484         return (TextModel) mText;
485     }
486 
getImage()487     public ImageModel getImage() {
488         return (ImageModel) mImage;
489     }
490 
getAudio()491     public AudioModel getAudio() {
492         return (AudioModel) mAudio;
493     }
494 
getVideo()495     public VideoModel getVideo() {
496         return (VideoModel) mVideo;
497     }
498 
updateDuration(int duration)499     public void updateDuration(int duration) {
500         if (duration <= 0) {
501             return;
502         }
503 
504         if ((duration > mDuration)
505                 || (mDuration == DEFAULT_SLIDE_DURATION)) {
506             mDuration = duration;
507         }
508     }
509 }
510