/*
* Frame.java
* Transform
*
* Copyright (c) 2001-2010 Flagstone Software Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Flagstone Software Ltd. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package com.flagstone.transform.util.movie;
import java.util.ArrayList;
import java.util.List;
import com.flagstone.transform.DefineTag;
import com.flagstone.transform.DoAction;
import com.flagstone.transform.FrameLabel;
import com.flagstone.transform.Movie;
import com.flagstone.transform.MovieTag;
import com.flagstone.transform.ShowFrame;
import com.flagstone.transform.action.Action;
/**
* <p>
* The Frame class is used to provide a higher level view of a movie. Rather
* than viewing movies as a sequence of individual objects each representing a
* given data structure in the encoded Flash file, objects can be grouped
* together in frames which presents a more logical view of a movie and makes
* movie manipulation and search for specific objects easier to handle.
* </p>
*
* <p>
* Each Frame object has the following attributes:<br/>
*
* <em>number</em> - The position in the movie when the frame will be displayed.
* <br/>
*
* <em>label</em> - An optional name assigned to a frame. The GotoFrame2 object
* can be used to move to a named frame when playing a movie or movie clip.<br/>
*
* <em>definitions</em> - A list containing objects that define items for
* display in a movie. Definitions are sub-classes of the Definition class and
* define shapes, fonts, images and sounds that are displayed or played by the
* Flash Player.<br/>
*
* <em>commands</em> - A list containing objects that define commands that
* affect the display list or the Flash Player directly.<br/>
*
* <em>actions</em> - A list that define actions that are executed when a
* frame is displayed.
* </p>
*
* <p>
* Frame objects simplify the handling of movies. DoAction, FrameLabel and
* ShowFrame classes can now "hidden" from view. They are generated
* automatically by the Frame object when it is added to an Movie object.
* </p>
*
* <p>
* The framesFromMovie(Movie aMovie) method allows an existing movie to be
* viewed as a list of Frame objects. Objects from the movie are copied into
* each frame so changes made to the attributes of each object are reflected in
* the movie. The frame objects are not synchronised with the movie, so any
* objects added to a frame are not added to the Movie. The easiest way to do
* this is to remove the existing objects from the movie and add all the frames.
* </p>
*
* <pre>
* ArrayList frames = Frame.framesFromMovie(aMovie);
* ...
* ...
* aMovie.getObjects().clear();
*
* for (Iterator i = frames.iterator(); i.hasNext();) {
* ((Frame)i.next()).addToMovie(aMovie);
* }
*</pre>
*
* <p>
* When the contents of an Frame object is added to a movie if a label defined
* then an FrameLabel object will be added. Similarly if actions are defined
* then an DoAction object will be added. An ShowFrame object which instructs
* the Flash Player to update the display list with all the changes is added.
* </p>
*
*/
public final class Frame {
/**
* Create a frame based view of a movie. Objects from the movie are grouped
* into Frame objects. Objects from the movie are added to the frame so any
* changes made are reflected in the movie. However objects added or removed
* from a frame are not reflected in the movie.
*
* @param aMovie
* an Movie object.
* @return a list of Frame objects.
*/
public static List<Frame> split(final Movie aMovie) {
final ArrayList<Frame> frames = new ArrayList<Frame>();
int index = 1;
Frame currentFrame = new Frame();
for (final MovieTag currentObject : aMovie.getObjects()) {
if (currentObject instanceof DoAction) {
currentFrame.actions = ((DoAction) currentObject).getActions();
} else if (currentObject instanceof FrameLabel) {
currentFrame.label = ((FrameLabel) currentObject).getLabel();
} else if (currentObject instanceof DefineTag) {
currentFrame.addDefinition(currentObject);
} else if (currentObject instanceof ShowFrame) {
currentFrame.setNumber(index++);
frames.add(currentFrame);
currentFrame = new Frame();
} else {
currentFrame.addCommand(currentObject);
}
}
return frames;
}
/** The frame label. */
private String label;
/** The frame number. */
private int number;
/** List of definitions. */
private List<MovieTag> definitions;
/** List of display list and other commands. */
private List<MovieTag> commands;
/** List of actions executed when the frame is displayed. */
private List<Action> actions;
/**
* Creates a empty frame with no label defined and the definitions, commands
* and actions lists empty.
*/
public Frame() {
definitions = new ArrayList<MovieTag>();
commands = new ArrayList<MovieTag>();
actions = new ArrayList<Action>();
}
/**
* Creates a empty frame with no label defined and the definitions, commands
* and actions lists empty.
*
* @param frame the frame number.
*/
public Frame(final int frame) {
setNumber(frame);
definitions = new ArrayList<MovieTag>();
commands = new ArrayList<MovieTag>();
actions = new ArrayList<Action>();
}
/**
* Adds the action object to the frame.
*
* @param anObject
* the action object to be added to the frame. Must not be null.
*/
public void addAction(final Action anObject) {
if (anObject == null) {
throw new IllegalArgumentException();
}
actions.add(anObject);
}
/**
* Adds an object to the frame that defines an object to be displayed in the
* movie.
*
* @param anObject
* a sub-class of Definition. Must not be null.
*/
public void addDefinition(final MovieTag anObject) {
if (anObject == null) {
throw new IllegalArgumentException();
}
definitions.add(anObject);
}
/**
* Adds the display list command to the frame.
*
* @param anObject
* an MovieTag the manipulates the display list. Must not be
* null.
*/
public void addCommand(final MovieTag anObject) {
if (anObject == null) {
throw new IllegalArgumentException();
}
commands.add(anObject);
}
/**
* Get the number of the frame.
*
* @return the frame number.
*/
public int getNumber() {
return number;
}
/**
* Returns the label assigned to the frame.
*
* @return the label. The string will be empty if no label is defined.
*/
public String getLabel() {
return label;
}
/**
* Returns the list of definition objects contained in the frame.
*
* @return the list of definitions.
*/
public List<MovieTag> getDefinitions() {
return definitions;
}
/**
* Returns the list of commands that update the display list.
*
* @return the list of commands objects.
*/
public List<MovieTag> getCommands() {
return commands;
}
/**
* Returns the array of action objects that will be execute when the frame
* is displayed.
*
* @return the array of actions defined for the frame.
*/
public List<Action> getActions() {
return actions;
}
/**
* Sets the number for the frame.
*
* @param frameNumber
* the frame number.
*/
public void setNumber(final int frameNumber) {
number = frameNumber;
}
/**
* Sets the label for the frame.
*
* @param aString
* the label.
*/
public void setLabel(final String aString) {
label = aString;
}
/**
* Sets the list of action objects for the frame.
*
* @param list
* the list of actions. Must not be null.
*/
public void setDefinitions(final List<MovieTag> list) {
if (list == null) {
throw new IllegalArgumentException();
}
definitions = list;
}
/**
* Sets the list of commands that updated the display list for the frame.
* The changes are visible when the frame is displayed.
*
* @param list
* the list of command objects. Must not be null.
*/
public void setCommands(final List<MovieTag> list) {
if (list == null) {
throw new IllegalArgumentException();
}
commands = list;
}
/**
* Sets the list of action objects for the frame.
*
* @param list
* the list of actions. Must not be null.
*/
public void setActions(final List<Action> list) {
if (list == null) {
throw new IllegalArgumentException();
}
actions = list;
}
/**
* Add the objects in the frame to the movie. The contents of the
* definitions and commands lists are added to the movie. If a label is
* assigned to the frame then an FrameLabel object is added to the movie. If
* actions are defined then an DoAction object is added containing the
* actions defined in the frame.
*
* @param aMovie
* an Movie object. Must not be null.
*/
public void addToMovie(final Movie aMovie) {
if (!definitions.isEmpty()) {
for (final MovieTag object : definitions) {
aMovie.add(object);
}
}
if (label.length() > 0) {
aMovie.add(new FrameLabel(label));
}
if (!actions.isEmpty()) {
aMovie.add(new DoAction(actions));
}
for (final MovieTag object : commands) {
aMovie.add(object);
}
aMovie.add(ShowFrame.getInstance());
}
}