/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mms.model;
import com.android.mms.ContentRestrictionException;
import com.android.mms.dom.smil.SmilParElementImpl;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.smil.ElementTime;
import android.util.Config;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class SlideModel extends Model
implements List<MediaModel>, EventListener {
private static final String TAG = "SlideModel";
private static final boolean DEBUG = false;
private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
private static final int DEFAULT_SLIDE_DURATION = 5000;
private final ArrayList<MediaModel> mMedia = new ArrayList<MediaModel>();
private MediaModel mText;
private MediaModel mImage;
private MediaModel mAudio;
private MediaModel mVideo;
private boolean mCanAddImage = true;
private boolean mCanAddAudio = true;
private boolean mCanAddVideo = true;
private int mDuration;
private boolean mVisible = true;
private short mFill;
private int mSlideSize;
private SlideshowModel mParent;
public SlideModel(SlideshowModel slideshow) {
this(DEFAULT_SLIDE_DURATION, slideshow);
}
public SlideModel(int duration, SlideshowModel slideshow) {
mDuration = duration;
mParent = slideshow;
}
/**
* Create a SlideModel with exist media collection.
*
* @param duration The duration of the slide.
* @param mediaList The exist media collection.
*
* @throws IllegalStateException One or more media in the mediaList cannot
* be added into the slide due to a slide cannot contain image
* and video or audio and video at the same time.
*/
public SlideModel(int duration, ArrayList<MediaModel> mediaList) {
mDuration = duration;
int maxDur = 0;
for (MediaModel media : mediaList) {
internalAdd(media);
int mediaDur = media.getDuration();
if (mediaDur > maxDur) {
maxDur = mediaDur;
}
}
updateDuration(maxDur);
}
private void internalAdd(MediaModel media) throws IllegalStateException {
if (media == null) {
// Don't add null value into the list.
return;
}
if (media.isText()) {
internalAddOrReplace(mText, media);
mText = media;
} else if (media.isImage()) {
if (mCanAddImage) {
internalAddOrReplace(mImage, media);
mImage = media;
mCanAddVideo = false;
} else {
throw new IllegalStateException();
}
} else if (media.isAudio()) {
if (mCanAddAudio) {
internalAddOrReplace(mAudio, media);
mAudio = media;
mCanAddVideo = false;
} else {
throw new IllegalStateException();
}
} else if (media.isVideo()) {
if (mCanAddVideo) {
internalAddOrReplace(mVideo, media);
mVideo = media;
mCanAddImage = false;
mCanAddAudio = false;
} else {
throw new IllegalStateException();
}
}
}
private void internalAddOrReplace(MediaModel old, MediaModel media) {
int addSize = media.getMediaSize();
int removeSize;
if (old == null) {
if (null != mParent) {
mParent.checkMessageSize(addSize);
}
mMedia.add(media);
increaseSlideSize(addSize);
increaseMessageSize(addSize);
} else {
removeSize = old.getMediaSize();
if (addSize > removeSize) {
if (null != mParent) {
mParent.checkMessageSize(addSize - removeSize);
}
increaseSlideSize(addSize - removeSize);
increaseMessageSize(addSize - removeSize);
} else {
decreaseSlideSize(removeSize - addSize);
decreaseMessageSize(removeSize - addSize);
}
mMedia.set(mMedia.indexOf(old), media);
old.unregisterAllModelChangedObservers();
}
for (IModelChangedObserver observer : mModelChangedObservers) {
media.registerModelChangedObserver(observer);
}
}
private boolean internalRemove(Object object) {
if (mMedia.remove(object)) {
if (object instanceof TextModel) {
mText = null;
} else if (object instanceof ImageModel) {
mImage = null;
mCanAddVideo = true;
} else if (object instanceof AudioModel) {
mAudio = null;
mCanAddVideo = true;
} else if (object instanceof VideoModel) {
mVideo = null;
mCanAddImage = true;
mCanAddAudio = true;
}
int decreaseSize = ((MediaModel) object).getMediaSize();
decreaseSlideSize(decreaseSize);
decreaseMessageSize(decreaseSize);
((Model) object).unregisterAllModelChangedObservers();
return true;
}
return false;
}
/**
* @return the mDuration
*/
public int getDuration() {
return mDuration;
}
/**
* @param duration the mDuration to set
*/
public void setDuration(int duration) {
mDuration = duration;
notifyModelChanged(true);
}
public int getSlideSize() {
return mSlideSize;
}
public void increaseSlideSize(int increaseSize) {
if (increaseSize > 0) {
mSlideSize += increaseSize;
}
}
public void decreaseSlideSize(int decreaseSize) {
if (decreaseSize > 0) {
mSlideSize -= decreaseSize;
}
}
public void setParent(SlideshowModel parent) {
mParent = parent;
}
public void increaseMessageSize(int increaseSize) {
if ((increaseSize > 0) && (null != mParent)) {
int size = mParent.getCurrentMessageSize();
size += increaseSize;
mParent.setCurrentMessageSize(size);
}
}
public void decreaseMessageSize(int decreaseSize) {
if ((decreaseSize > 0) && (null != mParent)) {
int size = mParent.getCurrentMessageSize();
size -= decreaseSize;
mParent.setCurrentMessageSize(size);
}
}
//
// Implement List<E> interface.
//
/**
* Add a MediaModel to the slide. If the slide has already contained
* a media object in the same type, the media object will be replaced by
* the new one.
*
* @param object A media object to be added into the slide.
* @return true
* @throws IllegalStateException One or more media in the mediaList cannot
* be added into the slide due to a slide cannot contain image
* and video or audio and video at the same time.
* @throws ContentRestrictionException when can not add this object.
*
*/
public boolean add(MediaModel object) {
internalAdd(object);
notifyModelChanged(true);
return true;
}
public boolean addAll(Collection<? extends MediaModel> collection) {
throw new UnsupportedOperationException("Operation not supported.");
}
public void clear() {
if (mMedia.size() > 0) {
for (MediaModel media : mMedia) {
media.unregisterAllModelChangedObservers();
int decreaseSize = media.getMediaSize();
decreaseSlideSize(decreaseSize);
decreaseMessageSize(decreaseSize);
}
mMedia.clear();
mText = null;
mImage = null;
mAudio = null;
mVideo = null;
mCanAddImage = true;
mCanAddAudio = true;
mCanAddVideo = true;
notifyModelChanged(true);
}
}
public boolean contains(Object object) {
return mMedia.contains(object);
}
public boolean containsAll(Collection<?> collection) {
return mMedia.containsAll(collection);
}
public boolean isEmpty() {
return mMedia.isEmpty();
}
public Iterator<MediaModel> iterator() {
return mMedia.iterator();
}
public boolean remove(Object object) {
if ((object != null) && (object instanceof MediaModel)
&& internalRemove(object)) {
notifyModelChanged(true);
return true;
}
return false;
}
public boolean removeAll(Collection<?> collection) {
throw new UnsupportedOperationException("Operation not supported.");
}
public boolean retainAll(Collection<?> collection) {
throw new UnsupportedOperationException("Operation not supported.");
}
public int size() {
return mMedia.size();
}
public Object[] toArray() {
return mMedia.toArray();
}
public <T> T[] toArray(T[] array) {
return mMedia.toArray(array);
}
public void add(int location, MediaModel object) {
throw new UnsupportedOperationException("Operation not supported.");
}
public boolean addAll(int location,
Collection<? extends MediaModel> collection) {
throw new UnsupportedOperationException("Operation not supported.");
}
public MediaModel get(int location) {
return mMedia.get(location);
}
public int indexOf(Object object) {
return mMedia.indexOf(object);
}
public int lastIndexOf(Object object) {
return mMedia.lastIndexOf(object);
}
public ListIterator<MediaModel> listIterator() {
return mMedia.listIterator();
}
public ListIterator<MediaModel> listIterator(int location) {
return mMedia.listIterator(location);
}
public MediaModel remove(int location) {
MediaModel media = mMedia.get(location);
if ((media != null) && internalRemove(media)) {
notifyModelChanged(true);
}
return media;
}
public MediaModel set(int location, MediaModel object) {
throw new UnsupportedOperationException("Operation not supported.");
}
public List<MediaModel> subList(int start, int end) {
return mMedia.subList(start, end);
}
/**
* @return the mVisible
*/
public boolean isVisible() {
return mVisible;
}
/**
* @param visible the mVisible to set
*/
public void setVisible(boolean visible) {
mVisible = visible;
notifyModelChanged(true);
}
/**
* @return the mFill
*/
public short getFill() {
return mFill;
}
/**
* @param fill the mFill to set
*/
public void setFill(short fill) {
mFill = fill;
notifyModelChanged(true);
}
@Override
protected void registerModelChangedObserverInDescendants(
IModelChangedObserver observer) {
for (MediaModel media : mMedia) {
media.registerModelChangedObserver(observer);
}
}
@Override
protected void unregisterModelChangedObserverInDescendants(
IModelChangedObserver observer) {
for (MediaModel media : mMedia) {
media.unregisterModelChangedObserver(observer);
}
}
@Override
protected void unregisterAllModelChangedObserversInDescendants() {
for (MediaModel media : mMedia) {
media.unregisterAllModelChangedObservers();
}
}
// EventListener Interface
public void handleEvent(Event evt) {
if (evt.getType().equals(SmilParElementImpl.SMIL_SLIDE_START_EVENT)) {
if (LOCAL_LOGV) {
Log.v(TAG, "Start to play slide: " + this);
}
mVisible = true;
} else if (mFill != ElementTime.FILL_FREEZE) {
if (LOCAL_LOGV) {
Log.v(TAG, "Stop playing slide: " + this);
}
mVisible = false;
}
notifyModelChanged(false);
}
public boolean hasText() {
return mText != null;
}
public boolean hasImage() {
return mImage != null;
}
public boolean hasAudio() {
return mAudio != null;
}
public boolean hasVideo() {
return mVideo != null;
}
public boolean removeText() {
return remove(mText);
}
public boolean removeImage() {
return remove(mImage);
}
public boolean removeAudio() {
return remove(mAudio);
}
public boolean removeVideo() {
return remove(mVideo);
}
public TextModel getText() {
return (TextModel) mText;
}
public ImageModel getImage() {
return (ImageModel) mImage;
}
public AudioModel getAudio() {
return (AudioModel) mAudio;
}
public VideoModel getVideo() {
return (VideoModel) mVideo;
}
public void updateDuration(int duration) {
if (duration <= 0) {
return;
}
if ((duration > mDuration)
|| (mDuration == DEFAULT_SLIDE_DURATION)) {
mDuration = duration;
}
}
}
|