/* * $RCSfile: TimeContainerSupport.java,v $ * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package com.sun.perseus.model; import java.util.Vector; import java.io.PrintStream; /** * * @version $Id: TimeContainerSupport.java,v 1.4 2006/06/29 10:47:35 ln156897 Exp $ */ public class TimeContainerSupport extends TimedElementSupport { /** * The container's current simple time */ protected Time simpleTime = Time.UNRESOLVED; /** * The set of children TimedElementSupport contained * in this container. */ protected Vector timedElementChildren = new Vector(5); /** * Default constructor */ public TimeContainerSupport() { } /** * @return this container's current simple time */ public Time getSimpleTime() { return simpleTime; } /** * Resets this container and all its children. This, in effect, moves the * container back to the begining of its timeline, i.e., prior to begining * the first interval. */ protected void initialize() { super.initialize(); // If a new interval was created, children have already been initialized // (see dispatchOnNewInterval). Otherwise, make sure we initialize the // full tree. if (currentInterval == null) { for (int i = 0; i < timedElementChildren.size(); i++) { TimedElementSupport child = (TimedElementSupport) timedElementChildren.elementAt(i); child.initialize(); } } } /** * When a container resets, it needs to clear all its children which have * IntervalTimeInstances on syncBases which are also children * (or descendants) of this container. * * @see <a href="http://www.w3.org/TR/smil20#smil-timing-Timing-ResetDefaultAttribute"> * SMIL 2 Specification, Resetting element state</a> */ void reset() { super.reset(); for (int i = 0; i < timedElementChildren.size(); i++) { TimedElementSupport child = (TimedElementSupport) timedElementChildren.elementAt(i); child.removeSyncBaseTimesUnder(this); } } /** * Removes all <code>IntervalTimeInstance</code>s in the begin and end * instance list if the syncBase is a descendant of syncTimeContainer * * @param syncTimeContainer the container under which times should be * removed. */ void removeSyncBaseTimesUnder( final TimeContainerSupport syncTimeContainer) { super.removeSyncBaseTimesUnder(syncTimeContainer); for (int i = 0; i < timedElementChildren.size(); i++) { TimedElementSupport child = (TimedElementSupport) timedElementChildren.elementAt(i); child.removeSyncBaseTimesUnder(syncTimeContainer); } } /** * Samples this time container at the given simple time. * * @param simpleTime this timed element's simple time. */ void sampleAt(final long simpleTime) { setSimpleTime(simpleTime); for (int i = 0; i < timedElementChildren.size(); i++) { TimedElementSupport child = (TimedElementSupport) timedElementChildren.elementAt(i); if (seeking) { child.seeking = true; child.sample(this.simpleTime); child.seeking = false; } else { child.sample(this.simpleTime); } } } /** * Dispatches endEvent. As per the SMIL 2 specification, this dispatches * an endEvent for the resolved end time, not the observed end * time. * * @param currentTime the current sampling time. * * @see <a href="http://www.w3.org/TR/smil20/smil-timing.html#Timing-BeginValueSemantics"> * SMIL2's Begin value semantics</a> */ void dispatchEndEvent(final Time currentTime) { super.dispatchEndEvent(currentTime); // Now, force children to end now. Before invoking children, we need // to update the container's simpleTime. long time = currentInterval.end.value - currentInterval.begin.value; if (simpleDur.isResolved()) { if (time > 0) { time = time % simpleDur.value; if (time == 0) { time = simpleDur.value; } } } endChildrenAt(time); } /** * Calls all the registered <code>TimeDependent</code>s so that they * are notified of a new TimeInterval creation. When a time container * creates a new interval, its children are re-initialized. */ void dispatchOnNewInterval() { super.dispatchOnNewInterval(); // Now, re-initialize all children. for (int i = 0; i < timedElementChildren.size(); i++) { TimedElementSupport child = (TimedElementSupport) timedElementChildren.elementAt(i); child.initialize(); } } /** * Implementation helper to set the simple time object. * * @param time the new simple time value */ void setSimpleTime(final long time) { if (simpleTime == Time.UNRESOLVED) { simpleTime = new Time(time); } else { simpleTime.value = time; } } /** * When a container starts a new iteration, it needs to: * - end its children at the end of the previous interval. * - reset its children. * * @param prevIter the last iteration this element was playing. * @param curIter the new iteration this element is playing. */ protected void onStartingRepeat(final int prevIter, final int curIter) { // First, force ending children at the end of the previous iteration. long time = currentInterval.begin.value + simpleDur.value * (prevIter + 1); endChildrenAt(time); // Now, reset the children so that they are ready for the next sampling // at the begining of current interval. for (int i = 0; i < timedElementChildren.size(); i++) { TimedElementSupport child = (TimedElementSupport) timedElementChildren.elementAt(i); child.initialize(); } } /** * Implementation helper. Ends all children at the requested input time. * * @param time the time, in this container's simple time system, at which * children should be stopped. */ void endChildrenAt(final long time) { setSimpleTime(time); // First, end all children. Adding end times does not cause a state // transition. To make the children transition to their new state, we // invoke sample in a second iteration (see below). for (int i = 0; i < timedElementChildren.size(); i++) { TimedElementSupport child = (TimedElementSupport) timedElementChildren.elementAt(i); child.end(); } // Now, sample children on the end time for (int i = 0; i < timedElementChildren.size(); i++) { TimedElementSupport child = (TimedElementSupport) timedElementChildren.elementAt(i); child.sample(simpleTime); } } /** * Debug method: Traces the container and all its children. */ /** * Traces this viewport tree */ void dump() { dump(this, "", System.err); } /** * Debug: traces the input ModelNode, using the input prefix * * @param t the node to dump * @param prefix the string used to prefix the node information * @param out the stream where the node structure is dumped. */ static void dump(final TimedElementSupport t, final String prefix, final PrintStream out) { out.println(prefix + t); if (t instanceof TimeContainerSupport) { TimeContainerSupport tc = (TimeContainerSupport) t; for (int i = 0; i < tc.timedElementChildren.size(); i++) { TimedElementSupport c = (TimedElementSupport) tc .timedElementChildren.elementAt(i); dump(c, prefix + "+--> ", out); } } } }