/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 org.apache.batik.anim.timing;
import java.util.Calendar;
import java.util.LinkedList;
import org.apache.batik.util.DoublyIndexedSet;
An abstract base class for the root time container element
for a document.
Author: Cameron McCormack Version: $Id: TimedDocumentRoot.java 1804130 2017-08-04 14:41:11Z ssteiner $
/**
* An abstract base class for the root time container element
* for a document.
*
* @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
* @version $Id: TimedDocumentRoot.java 1804130 2017-08-04 14:41:11Z ssteiner $
*/
public abstract class TimedDocumentRoot extends TimeContainer {
The wallclock time that the document began.
/**
* The wallclock time that the document began.
*/
protected Calendar documentBeginTime;
Allows the use of accessKey() timing specifiers with a single
character, as specified in SVG 1.1.
/**
* Allows the use of accessKey() timing specifiers with a single
* character, as specified in SVG 1.1.
*/
protected boolean useSVG11AccessKeys;
Allows the use of accessKey() timing specifiers with a DOM 3
key name, as specified in SVG 1.2.
/**
* Allows the use of accessKey() timing specifiers with a DOM 3
* key name, as specified in SVG 1.2.
*/
protected boolean useSVG12AccessKeys;
A set to determine when propagation of new Instance times should
be stopped.
/**
* A set to determine when propagation of new Instance times should
* be stopped.
*/
protected DoublyIndexedSet propagationFlags = new DoublyIndexedSet();
List of {link TimegraphListener}s to be notified of changes to the
timed elements in this document.
/**
* List of {link TimegraphListener}s to be notified of changes to the
* timed elements in this document.
*/
protected LinkedList listeners = new LinkedList();
Whether the document is currently being sampled.
/**
* Whether the document is currently being sampled.
*/
protected boolean isSampling;
Whether the document is currently being sampled for a hyperlink.
/**
* Whether the document is currently being sampled for a hyperlink.
*/
protected boolean isHyperlinking;
Creates a new TimedDocumentRoot.
Params: - useSVG11AccessKeys – allows the use of accessKey() timing
specifiers with a single character
- useSVG12AccessKeys – allows the use of accessKey() with a
DOM 3 key name
/**
* Creates a new TimedDocumentRoot.
* @param useSVG11AccessKeys allows the use of accessKey() timing
* specifiers with a single character
* @param useSVG12AccessKeys allows the use of accessKey() with a
* DOM 3 key name
*/
public TimedDocumentRoot(boolean useSVG11AccessKeys,
boolean useSVG12AccessKeys) {
root = this;
this.useSVG11AccessKeys = useSVG11AccessKeys;
this.useSVG12AccessKeys = useSVG12AccessKeys;
}
Returns the implicit duration of the element. The document root has an TimedElement.INDEFINITE
implicit duration. /**
* Returns the implicit duration of the element. The document root
* has an {@link #INDEFINITE} implicit duration.
*/
protected float getImplicitDur() {
return INDEFINITE;
}
Returns the default begin time for the given child
timed element. In SVG, this is always 0, since the
only time container is the root SVG element, which acts
like a 'par'.
/**
* Returns the default begin time for the given child
* timed element. In SVG, this is always 0, since the
* only time container is the root SVG element, which acts
* like a 'par'.
*/
public float getDefaultBegin(TimedElement child) {
return 0.0f;
}
Returns the last sampled document time.
/**
* Returns the last sampled document time.
*/
public float getCurrentTime() {
return lastSampleTime;
}
Returns whether the document is currently being sampled.
/**
* Returns whether the document is currently being sampled.
*/
public boolean isSampling() {
return isSampling;
}
Returns whether the document is currently being sampled for a hyperlink.
/**
* Returns whether the document is currently being sampled for a hyperlink.
*/
public boolean isHyperlinking() {
return isHyperlinking;
}
Samples the entire timegraph at the given time.
/**
* Samples the entire timegraph at the given time.
*/
public float seekTo(float time, boolean hyperlinking) {
// Trace.enter(this, "seekTo", new Object[] { Float.valueOf(time) } ); try {
isSampling = true;
lastSampleTime = time;
isHyperlinking = hyperlinking;
propagationFlags.clear();
// No time containers in SVG, so we don't have to worry
// about a partial ordering of timed elements to sample.
float mint = Float.POSITIVE_INFINITY;
TimedElement[] es = getChildren();
for (TimedElement e1 : es) {
float t = e1.sampleAt(time, hyperlinking);
if (t < mint) {
mint = t;
}
}
boolean needsUpdates;
do {
needsUpdates = false;
for (TimedElement e : es) {
if (e.shouldUpdateCurrentInterval) {
needsUpdates = true;
// System.err.print("{" + ((Test.AnimateElement) es[i]).id + "} ");
float t = e.sampleAt(time, hyperlinking);
if (t < mint) {
mint = t;
}
}
}
} while (needsUpdates);
isSampling = false;
if (hyperlinking) {
root.currentIntervalWillUpdate();
}
return mint;
// } finally { Trace.exit(); }
}
Resets the entire timegraph.
/**
* Resets the entire timegraph.
*/
public void resetDocument(Calendar documentBeginTime) {
if (documentBeginTime == null) {
this.documentBeginTime = Calendar.getInstance();
} else {
this.documentBeginTime = documentBeginTime;
}
reset(true);
}
Returns the wallclock time that the document began.
/**
* Returns the wallclock time that the document began.
*/
public Calendar getDocumentBeginTime() {
return documentBeginTime;
}
Converts an epoch time to document time.
/**
* Converts an epoch time to document time.
*/
public float convertEpochTime(long t) {
long begin = documentBeginTime.getTime().getTime();
return (t - begin) / 1000f;
}
Converts a wallclock time to document time.
/**
* Converts a wallclock time to document time.
*/
public float convertWallclockTime(Calendar time) {
long begin = documentBeginTime.getTime().getTime();
long t = time.getTime().getTime();
return (t - begin) / 1000f;
}
Adds a TimegraphListener
to the document. /**
* Adds a {@link TimegraphListener} to the document.
*/
public void addTimegraphListener(TimegraphListener l) {
listeners.add(l);
}
Removes a TimegraphListener
from the document. /**
* Removes a {@link TimegraphListener} from the document.
*/
public void removeTimegraphListener(TimegraphListener l) {
listeners.remove(l);
}
Fires an TimegraphListener.elementAdded
event on all timegraph listeners. /**
* Fires an {@link TimegraphListener#elementAdded} event on all
* timegraph listeners.
*/
void fireElementAdded(TimedElement e) {
for (Object listener : listeners) {
((TimegraphListener) listener).elementAdded(e);
}
}
Fires an TimegraphListener.elementRemoved
event on all timegraph listeners. /**
* Fires an {@link TimegraphListener#elementRemoved} event on all
* timegraph listeners.
*/
void fireElementRemoved(TimedElement e) {
for (Object listener : listeners) {
((TimegraphListener) listener).elementRemoved(e);
}
}
// XXX Add fire* methods for the other events in TimegraphListener, and make
// TimedElement fire them.
Returns whether the specified newly created Interval
should propagate its times to the given TimingSpecifier
. Params: - i – the Interval that has just been created
- ts – the TimingSpecifier that is a dependent of the Interval
- isBegin – whether the dependency is on the begin or end time of
the Interval
/**
* Returns whether the specified newly created {@link Interval} should
* propagate its times to the given {@link TimingSpecifier}.
* @param i the Interval that has just been created
* @param ts the TimingSpecifier that is a dependent of the Interval
* @param isBegin whether the dependency is on the begin or end time of
* the Interval
*/
boolean shouldPropagate(Interval i, TimingSpecifier ts, boolean isBegin) {
InstanceTime it = isBegin ? i.getBeginInstanceTime()
: i.getEndInstanceTime();
if (propagationFlags.contains(it, ts)) {
return false;
}
propagationFlags.add(it, ts);
return true;
}
Invoked by timed elements in this document to indicate that the current
interval will be re-evaluated at the next sample. This should be
overridden in a concrete class so that ticks can be scheduled immediately
if they are currently paused due to no animations being active.
/**
* Invoked by timed elements in this document to indicate that the current
* interval will be re-evaluated at the next sample. This should be
* overridden in a concrete class so that ticks can be scheduled immediately
* if they are currently paused due to no animations being active.
*/
protected void currentIntervalWillUpdate() {
}
Returns the namespace URI of the event that corresponds to the given
animation event name.
/**
* Returns the namespace URI of the event that corresponds to the given
* animation event name.
*/
protected abstract String getEventNamespaceURI(String eventName);
Returns the type of the event that corresponds to the given
animation event name.
/**
* Returns the type of the event that corresponds to the given
* animation event name.
*/
protected abstract String getEventType(String eventName);
Returns the name of the repeat event.
Returns: either "repeat" or "repeatEvent"
/**
* Returns the name of the repeat event.
* @return either "repeat" or "repeatEvent"
*/
protected abstract String getRepeatEventName();
}