[Libreoffice-commits] .: 13 commits - filter/source sd/source sd/xml
Marco Cecchetti
mcecchetti at kemper.freedesktop.org
Sun Jul 15 02:54:24 PDT 2012
filter/source/svg/presentation_engine.js | 1252 ++++++++++++++++++++++++++-----
sd/source/core/CustomAnimationEffect.cxx | 13
sd/xml/effects.xml | 12
3 files changed, 1102 insertions(+), 175 deletions(-)
New commits:
commit 821b01bf2c5046f6731fa537bc034a45c176f265
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Sun Jul 15 10:54:49 2012 +0200
JavaScript engine: added support for skipping/rewinding an effect belonging to an interactive animation sequence.
Moreover now when the mouse pointer is over an event-source shape, through which the
user can start an interactive animation, the cursor appearance is changed to a hand
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index cccbcd0..88d8de0 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -3006,7 +3006,7 @@ function skipEffects(dir)
{
if( dir == 1 )
{
- var bRet = aSlideShow.skipEffect();
+ var bRet = aSlideShow.skipPlayingOrNextEffect();
if( !bRet )
{
@@ -5145,6 +5145,7 @@ function BaseNode( aAnimElem, aParentNode, aNodeContext )
this.aDuration = null;
this.aEnd = null;
this.bMainSequenceRootNode = false;
+ this.bInteractiveSequenceRootNode = false;
this.eFillMode = FILL_MODE_FREEZE;
this.eRestartMode = RESTART_MODE_NEVER;
this.nReapeatCount = undefined;
@@ -5462,6 +5463,11 @@ BaseNode.prototype.isMainSequenceRootNode = function()
return this.bMainSequenceRootNode;
};
+BaseNode.prototype.isInteractiveSequenceRootNode = function()
+{
+ return this.bInteractiveSequenceRootNode;
+};
+
BaseNode.prototype.makeDeactivationEvent = function( nDelay )
{
if( this.aDeactivationEvent )
@@ -5528,6 +5534,8 @@ BaseNode.prototype.notifyEndListeners = function()
}
this.aContext.aEventMultiplexer.notifyEvent( EVENT_TRIGGER_END_EVENT, this.getId() );
+ if( this.getParentNode() && this.getParentNode().isMainSequenceRootNode() )
+ this.aContext.aEventMultiplexer.notifyNextEffectEndEvent();
};
BaseNode.prototype.getContext = function()
@@ -6123,6 +6131,7 @@ BaseContainerNode.prototype.parseElement= function()
if( sNodeTypeAttr && aImpressNodeTypeInMap[ sNodeTypeAttr ] )
this.eImpressNodeType = aImpressNodeTypeInMap[ sNodeTypeAttr ];
this.bMainSequenceRootNode = ( this.eImpressNodeType == IMPRESS_MAIN_SEQUENCE_NODE );
+ this.bInteractiveSequenceRootNode = ( this.eImpressNodeType == IMPRESS_INTERACTIVE_SEQUENCE_NODE );
// preset-class attribute
this.ePresetClass = undefined;
@@ -6554,6 +6563,7 @@ SequentialTimeContainer.prototype.rewindCurrentEffect = function( aChildNode )
// resolve it again.
aChildNode.init();
this.resolveChild( aChildNode );
+ this.notifyRewindedEvent( aChildNode );
this.bIsRewinding = false;
}
else
@@ -6582,12 +6592,17 @@ SequentialTimeContainer.prototype.rewindLastEffect = function( aChildNode )
// immediately without increment the finished children counter and
// resolve the next child.
this.bIsRewinding = true;
- // We end the current effect and remove any change it applies on the
- // animated shape.
+ // We end the current effect.
this.getContext().aTimerEventQueue.forceEmpty();
this.getContext().aActivityQueue.clear();
aChildNode.end();
- aChildNode.removeEffect();
+ // Invoking the end method on the current child node that has not yet
+ // been activated should not lead to any change on the animated shape.
+ // However for safety we used to call the removeEffect method but
+ // lately we noticed that when interactive animation sequences are
+ // involved into the shape effect invoking such a method causes
+ // some issue.
+ //aChildNode.removeEffect();
// As we rewind the previous effect we need to decrease the finished
// children counter.
@@ -6603,6 +6618,7 @@ SequentialTimeContainer.prototype.rewindLastEffect = function( aChildNode )
// in ENDED state now, On the contrary it cannot be resolved again later.
aChildNode.init();
this.resolveChild( aPreviousChildNode );
+ this.notifyRewindedEvent( aChildNode );
this.bIsRewinding = false;
}
else
@@ -6629,29 +6645,50 @@ SequentialTimeContainer.prototype.resolveChild = function( aChildNode )
{
var bResolved = aChildNode.resolve();
- if( bResolved && this.isMainSequenceRootNode() )
+ if( bResolved && ( this.isMainSequenceRootNode() || this.isInteractiveSequenceRootNode() ) )
{
if( this.aCurrentSkipEvent )
this.aCurrentSkipEvent.dispose();
-
this.aCurrentSkipEvent = makeEvent( bind2( SequentialTimeContainer.prototype.skipEffect, this, aChildNode ) );
- this.aContext.aEventMultiplexer.registerSkipEffectEvent( this.aCurrentSkipEvent );
if( this.aRewindCurrentEffectEvent )
this.aRewindCurrentEffectEvent.dispose();
-
this.aRewindCurrentEffectEvent = makeEvent( bind2( SequentialTimeContainer.prototype.rewindCurrentEffect, this, aChildNode ) );
- this.aContext.aEventMultiplexer.registerRewindCurrentEffectEvent( this.aRewindCurrentEffectEvent );
if( this.aRewindLastEffectEvent )
this.aRewindLastEffectEvent.dispose();
-
this.aRewindLastEffectEvent = makeEvent( bind2( SequentialTimeContainer.prototype.rewindLastEffect, this, aChildNode ) );
- this.aContext.aEventMultiplexer.registerRewindLastEffectEvent( this.aRewindLastEffectEvent );
+
+ if( this.isMainSequenceRootNode() )
+ {
+ this.aContext.aEventMultiplexer.registerSkipEffectEvent( this.aCurrentSkipEvent );
+ this.aContext.aEventMultiplexer.registerRewindCurrentEffectEvent( this.aRewindCurrentEffectEvent );
+ this.aContext.aEventMultiplexer.registerRewindLastEffectEvent( this.aRewindLastEffectEvent );
+ }
+ else if( this.isInteractiveSequenceRootNode() )
+ {
+ this.aContext.aEventMultiplexer.registerSkipInteractiveEffectEvent( aChildNode.getId(), this.aCurrentSkipEvent );
+ this.aContext.aEventMultiplexer.registerRewindRunningInteractiveEffectEvent( aChildNode.getId(), this.aRewindCurrentEffectEvent );
+ this.aContext.aEventMultiplexer.registerRewindEndedInteractiveEffectEvent( aChildNode.getId(), this.aRewindLastEffectEvent );
+ }
}
return bResolved;
};
+SequentialTimeContainer.prototype.notifyRewindedEvent = function( aChildNode )
+{
+ if( this.isInteractiveSequenceRootNode() )
+ {
+ this.aContext.aEventMultiplexer.notifyRewindedEffectEvent( aChildNode.getId() );
+
+ var sId = aChildNode.getBegin().getEventBaseElementId();
+ if( sId )
+ {
+ this.aContext.aEventMultiplexer.notifyRewindedEffectEvent( sId );
+ }
+ }
+};
+
SequentialTimeContainer.prototype.dispose = function()
{
if( this.aCurrentSkipEvent )
@@ -8714,7 +8751,6 @@ AnimatedElement.prototype.restoreState = function( nAnimationNodeId )
}
ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').restoreState(' + nAnimationNodeId +')' );
-
var aState = this.aStateSet[ nAnimationNodeId ];
var bRet = this.setToElement( aState.aElement );
if( bRet )
@@ -9670,6 +9706,8 @@ function registerEvent( nNodeId, aTiming, aEvent, aNodeContext )
{
case EVENT_TRIGGER_ON_CLICK:
aEventMultiplexer.registerEvent( eEventType, aSourceEventElement.getId(), aEvent );
+ aEventMultiplexer.registerRewindedEffectHandler( aSourceEventElement.getId(),
+ bind2( aSourceEventElement.charge, aSourceEventElement ) );
bEventRegistered = true;
break;
default:
@@ -9681,6 +9719,11 @@ function registerEvent( nNodeId, aTiming, aEvent, aNodeContext )
var aEndEvent = aInteractiveAnimationSequenceMap[ nNodeId ].getEndEvent();
aEventMultiplexer.registerEvent( eEventType, aSourceEventElement.getId(), aStartEvent );
aEventMultiplexer.registerEvent( EVENT_TRIGGER_END_EVENT, nNodeId, aEndEvent );
+ aEventMultiplexer.registerRewindedEffectHandler(
+ nNodeId,
+ bind2( InteractiveAnimationSequence.prototype.chargeEvents,
+ aInteractiveAnimationSequenceMap[ nNodeId ] )
+ );
}
}
else // no base event element present
@@ -9754,16 +9797,19 @@ SourceEventElement.prototype.getId = function()
SourceEventElement.prototype.onMouseEnter = function()
{
this.bIsPointerOver = true;
+ this.setPointerCursor();
};
SourceEventElement.prototype.onMouseLeave = function()
{
this.bIsPointerOver = false;
+ this.setDefaultCursor();
};
SourceEventElement.prototype.charge = function()
{
this.bClickHandled = false;
+ this.setPointerCursor();
};
SourceEventElement.prototype.handleClick = function( aMouseEvent )
@@ -9771,14 +9817,27 @@ SourceEventElement.prototype.handleClick = function( aMouseEvent )
if( !this.bIsPointerOver ) return false;
if( this.bClickHandled )
- return true;
+ return false;
this.aEventMultiplexer.notifyEvent( EVENT_TRIGGER_ON_CLICK, this.getId() );
aSlideShow.update();
this.bClickHandled = true;
+ this.setDefaultCursor();
return true;
};
+SourceEventElement.prototype.setPointerCursor = function()
+{
+ if( this.bClickHandled )
+ return;
+
+ this.aElement.setAttribute( 'style', 'cursor: pointer' );
+};
+
+SourceEventElement.prototype.setDefaultCursor = function()
+{
+ this.aElement.setAttribute( 'style', 'cursor: default' );
+};
// ------------------------------------------------------------------------------------------ //
@@ -9876,10 +9935,15 @@ function EventMultiplexer( aTimerEventQueue )
{
this.aTimerEventQueue = aTimerEventQueue;
this.aEventMap = new Object();
+ this.aSkipEffectEndHandlerSet = new Array();
this.aMouseClickHandlerSet = new PriorityQueue( PriorityEntry.compare );
this.aSkipEffectEvent = null;
this.aRewindCurrentEffectEvent = null;
this.aRewindLastEffectEvent = null;
+ this.aSkipInteractiveEffectEventSet = new Object();
+ this.aRewindRunningInteractiveEffectEventSet = new Object();
+ this.aRewindEndedInteractiveEffectEventSet = new Object();
+ this.aRewindedEffectHandlerSet = new Object();
}
EventMultiplexer.prototype.registerMouseClickHandler = function( aHandler, nPriority )
@@ -9932,6 +9996,21 @@ EventMultiplexer.prototype.notifyEvent = function( eEventType, aNotifierId )
}
};
+EventMultiplexer.prototype.registerNextEffectEndHandler = function( aHandler )
+{
+ this.aSkipEffectEndHandlerSet.push( aHandler );
+};
+
+EventMultiplexer.prototype.notifyNextEffectEndEvent = function()
+{
+ var nSize = this.aSkipEffectEndHandlerSet.length;
+ for( var i = 0; i < nSize; ++i )
+ {
+ (this.aSkipEffectEndHandlerSet[i])();
+ }
+ this.aSkipEffectEndHandlerSet = new Array();
+};
+
EventMultiplexer.prototype.registerSkipEffectEvent = function( aEvent )
{
this.aSkipEffectEvent = aEvent;
@@ -9974,6 +10053,59 @@ EventMultiplexer.prototype.notifyRewindLastEffectEvent = function()
}
};
+EventMultiplexer.prototype.registerSkipInteractiveEffectEvent = function( nNotifierId, aEvent )
+{
+ this.aSkipInteractiveEffectEventSet[ nNotifierId ] = aEvent;
+};
+
+EventMultiplexer.prototype.notifySkipInteractiveEffectEvent = function( nNotifierId )
+{
+ if( this.aSkipInteractiveEffectEventSet[ nNotifierId ] )
+ {
+ this.aTimerEventQueue.addEvent( this.aSkipInteractiveEffectEventSet[ nNotifierId ] );
+ }
+};
+
+EventMultiplexer.prototype.registerRewindRunningInteractiveEffectEvent = function( nNotifierId, aEvent )
+{
+ this.aRewindRunningInteractiveEffectEventSet[ nNotifierId ] = aEvent;
+};
+
+EventMultiplexer.prototype.notifyRewindRunningInteractiveEffectEvent = function( nNotifierId )
+{
+ if( this.aRewindRunningInteractiveEffectEventSet[ nNotifierId ] )
+ {
+ this.aTimerEventQueue.addEvent( this.aRewindRunningInteractiveEffectEventSet[ nNotifierId ] );
+ }
+};
+
+EventMultiplexer.prototype.registerRewindEndedInteractiveEffectEvent = function( nNotifierId, aEvent )
+{
+ this.aRewindEndedInteractiveEffectEventSet[ nNotifierId ] = aEvent;
+};
+
+EventMultiplexer.prototype.notifyRewindEndedInteractiveEffectEvent = function( nNotifierId )
+{
+ if( this.aRewindEndedInteractiveEffectEventSet[ nNotifierId ] )
+ {
+ this.aTimerEventQueue.addEvent( this.aRewindEndedInteractiveEffectEventSet[ nNotifierId ] );
+ }
+};
+
+EventMultiplexer.prototype.registerRewindedEffectHandler = function( aNotifierId, aHandler )
+{
+ this.aRewindedEffectHandlerSet[ aNotifierId ] = aHandler;
+};
+
+EventMultiplexer.prototype.notifyRewindedEffectEvent = function( aNotifierId )
+{
+ if( this.aRewindedEffectHandlerSet[ aNotifierId ] )
+ {
+ (this.aRewindedEffectHandlerSet[ aNotifierId ])();
+ }
+};
+
+
EventMultiplexer.DEBUG = aEventMultiplexerDebugPrinter.isEnabled();
EventMultiplexer.prototype.DBG = function( sMethodName, eEventType, aNotifierId, nTime )
@@ -11419,6 +11551,49 @@ var PREFERRED_FRAMES_PER_SECONDS = 50;
var PREFERRED_FRAME_RATE = 1.0 / PREFERRED_FRAMES_PER_SECONDS;
+function Effect( nId )
+{
+ this.nId = ( typeof( nId ) === typeof( 1 ) ) ? nId : -1;
+ this.eState = Effect.NOT_STARTED;
+};
+
+Effect.NOT_STARTED = 0;
+Effect.PLAYING = 1;
+Effect.ENDED = 2;
+
+Effect.prototype.getId = function()
+{
+ return this.nId;
+};
+
+Effect.prototype.isMainEffect = function()
+{
+ return ( this.nId === -1 );
+};
+
+Effect.prototype.isPlaying = function()
+{
+ return ( this.eState === Effect.PLAYING );
+};
+
+Effect.prototype.isEnded = function()
+{
+ return ( this.eState === Effect.ENDED );
+};
+
+Effect.prototype.start = function()
+{
+ assert( this.eState === Effect.NOT_STARTED, 'Effect.start: wrong state.' );
+ this.eState = Effect.PLAYING;
+};
+
+Effect.prototype.end = function()
+{
+ assert( this.eState === Effect.PLAYING, 'Effect.end: wrong state.' );
+ this.eState = Effect.ENDED;
+};
+
+// ------------------------------------------------------------------------------------------ //
function SlideShow()
{
@@ -11435,18 +11610,21 @@ function SlideShow()
this.aNextEffectEventArray,
this.aInteractiveAnimationSequenceMap,
this.aActivityQueue );
- this.nCurrentEffect = 0;
- this.eDirection = FORWARD;
- this.nTotalInteracAnimSeqRunning = 0;
this.bIsIdle = true;
this.bIsEnabled = true;
+ this.bNoSlideTransition = false;
+
+ this.nCurrentEffect = 0;
+ this.bIsNextEffectRunning = false;
this.bIsRewinding = false;
this.bIsSkipping = false;
this.bIsSkippingAll = false;
- this.bNoSlideTransition = false;
+ this.nTotalInteractivePlayingEffects = 0;
+ this.aStartedEffectList = new Array();
+ this.aStartedEffectIndexMap = new Object();
+ this.aStartedEffectIndexMap[ -1 ] = undefined;
}
-
SlideShow.prototype.setSlideEvents = function( aNextEffectEventArray,
aInteractiveAnimationSequenceMap,
aEventMultiplexer )
@@ -11467,7 +11645,6 @@ SlideShow.prototype.setSlideEvents = function( aNextEffectEventArray,
this.aContext.aEventMultiplexer = aEventMultiplexer;
this.aEventMultiplexer = aEventMultiplexer;
this.nCurrentEffect = 0;
- this.nTotalInteracAnimSeqRunning = 0;
};
SlideShow.prototype.createSlideTransition = function( aSlideTransitionHandler, aLeavingSlide, aEnteringSlide, aTransitionEndEvent )
@@ -11512,30 +11689,74 @@ SlideShow.prototype.createSlideTransition = function( aSlideTransitionHandler, a
};
+SlideShow.prototype.isEnabled = function()
+{
+ return this.bIsEnabled;
+};
+
SlideShow.prototype.isRunning = function()
{
return !this.bIsIdle;
};
-SlideShow.prototype.isInterAnimSeqRunning = function()
+SlideShow.prototype.isMainEffectPlaying = function()
{
- return ( this.nTotalInteracAnimSeqRunning > 0 );
+ return this.bIsNextEffectRunning;
};
-SlideShow.prototype.isEnabled = function()
+SlideShow.prototype.isInteractiveEffectPlaying = function()
{
- return this.bIsEnabled;
+ return ( this.nTotalInteractivePlayingEffects > 0 );
+};
+
+SlideShow.prototype.isAnyEffectPlaying = function()
+{
+ return ( this.isMainEffectPlaying() || this.isInteractiveEffectPlaying() );
+};
+
+SlideShow.prototype.hasAnyEffectStarted = function()
+{
+ return ( this.aStartedEffectList.length > 0 );
};
SlideShow.prototype.notifyNextEffectStart = function()
{
+ assert( !this.bIsNextEffectRunning,
+ 'SlideShow.notifyNextEffectStart: an effect is already started.' );
+ this.bIsNextEffectRunning = true;
+ this.aEventMultiplexer.registerNextEffectEndHandler( bind2( SlideShow.prototype.notifyNextEffectEnd, this ) );
+ var aEffect = new Effect();
+ aEffect.start();
+ this.aStartedEffectIndexMap[ -1 ] = this.aStartedEffectList.length;
+ this.aStartedEffectList.push( aEffect );
+
+
var aAnimatedElementMap = theMetaDoc.aMetaSlideSet[nCurSlide].aSlideAnimationsHandler.aAnimatedElementMap;
for( var sId in aAnimatedElementMap )
aAnimatedElementMap[ sId ].notifyNextEffectStart( this.nCurrentEffect );
};
+SlideShow.prototype.notifyNextEffectEnd = function()
+{
+ assert( this.bIsNextEffectRunning,
+ 'SlideShow.notifyNextEffectEnd: effect already ended.' );
+ this.bIsNextEffectRunning = false;
+
+ this.aStartedEffectList[ this.aStartedEffectIndexMap[ -1 ] ].end();
+};
+
SlideShow.prototype.notifySlideStart = function( nSlideIndex )
{
+ this.nCurrentEffect = 0;
+ this.bIsRewinding = false;
+ this.bIsSkipping = false;
+ this.bIsSkippingAll = false;
+ this.nTotalInteractivePlayingEffects = 0;
+ this.aStartedEffectList = new Array();
+ this.aStartedEffectIndexMap = new Object();
+ this.aStartedEffectIndexMap[ -1 ] = undefined;
+
+
var aAnimatedElementMap = theMetaDoc.aMetaSlideSet[nSlideIndex].aSlideAnimationsHandler.aAnimatedElementMap;
for( var sId in aAnimatedElementMap )
aAnimatedElementMap[ sId ].notifySlideStart();
@@ -11556,88 +11777,108 @@ SlideShow.prototype.notifyTransitionEnd = function( nSlideIndex )
SlideShow.prototype.notifyInteractiveAnimationSequenceStart = function( nNodeId )
{
- ++this.nTotalInteracAnimSeqRunning;
+ ++this.nTotalInteractivePlayingEffects;
+ var aEffect = new Effect( nNodeId );
+ aEffect.start();
+ this.aStartedEffectIndexMap[ nNodeId ] = this.aStartedEffectList.length;
+ this.aStartedEffectList.push( aEffect );
};
SlideShow.prototype.notifyInteractiveAnimationSequenceEnd = function( nNodeId )
{
- assert( this.nTotalInteracAnimSeqRunning > 0,
- 'SlideShow.notifyInteractiveAnimationSequenceStart: ' +
- 'the total number of running interactive application is zero' );
- --this.nTotalInteracAnimSeqRunning;
+ assert( this.isInteractiveEffectPlaying(),
+ 'SlideShow.notifyInteractiveAnimationSequenceEnd: no interactive effect playing.' )
+
+ this.aStartedEffectList[ this.aStartedEffectIndexMap[ nNodeId ] ].end();
+ --this.nTotalInteractivePlayingEffects;
};
+/** nextEffect
+ * Start the next effect belonging to the main animation sequence if any.
+ * If there is an already playing effect belonging to any animation sequence
+ * it is skipped.
+ *
+ * @return {Boolean}
+ * False if there is no more effect to start, true otherwise.
+ */
SlideShow.prototype.nextEffect = function()
{
if( !this.isEnabled() )
return false;
- if( this.isInterAnimSeqRunning() )
- return true;
-
- if( this.isRunning() )
+ if( this.isAnyEffectPlaying() )
{
- this.skipCurrentEffect();
+ this.skipAllPlayingEffects();
return true;
}
if( !this.aNextEffectEventArray )
return false;
- this.notifyNextEffectStart();
-
if( this.nCurrentEffect >= this.aNextEffectEventArray.size() )
return false;
- this.eDirection = FORWARD;
+ this.notifyNextEffectStart();
+
this.aNextEffectEventArray.at( this.nCurrentEffect ).fire();
++this.nCurrentEffect;
this.update();
return true;
};
-/** skipCurrentEffect
- * Skip the current playing effect.
+/** skipAllPlayingEffects
+ * Skip all playing effect, independently to which animation sequence they
+ * belong.
*
*/
-SlideShow.prototype.skipCurrentEffect = function()
+SlideShow.prototype.skipAllPlayingEffects = function()
{
if( this.bIsSkipping || this.bIsRewinding )
- return;
+ return true;
this.bIsSkipping = true;
- this.aEventMultiplexer.notifySkipEffectEvent();
+ // TODO: The correct order should be based on the left playing time.
+ for( var i = 0; i < this.aStartedEffectList.length; ++i )
+ {
+ var aEffect = this.aStartedEffectList[i];
+ if( aEffect.isPlaying() )
+ {
+ if( aEffect.isMainEffect() )
+ this.aEventMultiplexer.notifySkipEffectEvent();
+ else
+ this.aEventMultiplexer.notifySkipInteractiveEffectEvent( aEffect.getId() );
+ }
+ }
this.update();
this.bIsSkipping = false;
+ return true;
};
-/** skipEffect
- * Skip the next effect to be played.
+/** skipNextEffect
+ * Skip the next effect to be played (if any) that belongs to the main
+ * animation sequence.
+ * Require: no effect is playing.
*
+ * @return {Boolean}
+ * False if there is no more effect to skip, true otherwise.
*/
-SlideShow.prototype.skipEffect = function()
+SlideShow.prototype.skipNextEffect = function()
{
if( this.bIsSkipping || this.bIsRewinding )
return true;
- if( this.isInterAnimSeqRunning() )
- return true;
-
- if( this.isRunning() )
- {
- this.skipCurrentEffect();
- return true;
- }
+ assert( !this.isAnyEffectPlaying(),
+ 'SlideShow.skipNextEffect' );
if( !this.aNextEffectEventArray )
return false;
- this.notifyNextEffectStart();
if( this.nCurrentEffect >= this.aNextEffectEventArray.size() )
return false;
+ this.notifyNextEffectStart();
+
this.bIsSkipping = true;
- this.eDirection = FORWARD;
this.aNextEffectEventArray.at( this.nCurrentEffect ).fire();
this.aEventMultiplexer.notifySkipEffectEvent();
++this.nCurrentEffect;
@@ -11646,8 +11887,25 @@ SlideShow.prototype.skipEffect = function()
return true;
};
+/** skipPlayingOrNextEffect
+ * Skip the next effect to be played that belongs to the main animation
+ * sequence or all playing effects.
+ *
+ * @return {Boolean}
+ * False if there is no more effect to skip, true otherwise.
+ */
+SlideShow.prototype.skipPlayingOrNextEffect = function()
+{
+ if( this.isAnyEffectPlaying() )
+ return this.skipAllPlayingEffects();
+ else
+ return this.skipNextEffect();
+};
+
+
/** skipAllEffects
- * Skip all left effects on the current slide.
+ * Skip all left effects that belongs to the main animation sequence and all
+ * playing effects on the current slide.
*
* @return {Boolean}
* True if it already skipping or when it has ended skipping,
@@ -11658,13 +11916,11 @@ SlideShow.prototype.skipAllEffects = function()
if( this.bIsSkippingAll )
return true;
- if( this.isInterAnimSeqRunning() )
- return true;
-
this.bIsSkippingAll = true;
- if( this.isRunning() )
+
+ if( this.isAnyEffectPlaying() )
{
- this.skipCurrentEffect();
+ this.skipAllPlayingEffects();
}
else if( !this.aNextEffectEventArray
|| ( this.nCurrentEffect >= this.aNextEffectEventArray.size() ) )
@@ -11681,14 +11937,16 @@ SlideShow.prototype.skipAllEffects = function()
// aNextEffectEventArray will going on increasing after every skip action.
while( this.nCurrentEffect < this.aNextEffectEventArray.size() )
{
- this.skipEffect();
+ this.skipNextEffect();
}
this.bIsSkippingAll = false;
return true;
};
/** rewindEffect
- * Rewind the current playing effect or the last played one.
+ * Rewind all the effects started after at least one of the current playing
+ * effects. If there is no playing effect, it rewinds the last played one,
+ * both in case it belongs to the main or to an interactive animation sequence.
*
*/
SlideShow.prototype.rewindEffect = function()
@@ -11696,37 +11954,105 @@ SlideShow.prototype.rewindEffect = function()
if( this.bIsSkipping || this.bIsRewinding )
return;
- if( this.isInterAnimSeqRunning() )
- return true;
-
- if( this.nCurrentEffect == 0 )
+ if( !this.hasAnyEffectStarted() )
{
this.rewindToPreviousSlide();
return;
}
this.bIsRewinding = true;
- if( this.isRunning() )
+
+ var nFirstPlayingEffectIndex = undefined;
+
+ var i = 0;
+ for( ; i < this.aStartedEffectList.length; ++i )
{
- this.aEventMultiplexer.notifyRewindCurrentEffectEvent();
+ var aEffect = this.aStartedEffectList[i];
+ if( aEffect.isPlaying() )
+ {
+ nFirstPlayingEffectIndex = i;
+ break;
+ }
}
- else
+
+ // There is at least one playing effect.
+ if( nFirstPlayingEffectIndex !== undefined )
+ {
+ i = this.aStartedEffectList.length - 1;
+ for( ; i >= nFirstPlayingEffectIndex; --i )
+ {
+ aEffect = this.aStartedEffectList[i];
+ if( aEffect.isPlaying() )
+ {
+ if( aEffect.isMainEffect() )
+ {
+ this.aEventMultiplexer.notifyRewindCurrentEffectEvent();
+ if( this.nCurrentEffect > 0 )
+ --this.nCurrentEffect;
+ }
+ else
+ {
+ this.aEventMultiplexer.notifyRewindRunningInteractiveEffectEvent( aEffect.getId() );
+ }
+ }
+ else if( aEffect.isEnded() )
+ {
+ if( aEffect.isMainEffect() )
+ {
+ this.aEventMultiplexer.notifyRewindLastEffectEvent();
+ if( this.nCurrentEffect > 0 )
+ --this.nCurrentEffect;
+ }
+ else
+ {
+ this.aEventMultiplexer.notifyRewindEndedInteractiveEffectEvent( aEffect.getId() );
+ }
+ }
+ }
+ this.update();
+
+ // Pay attention here: we need to remove all rewinded effects from
+ // the started effect list only after updating.
+ i = this.aStartedEffectList.length - 1;
+ for( ; i >= nFirstPlayingEffectIndex; --i )
+ {
+ aEffect = this.aStartedEffectList.pop();
+ if( !aEffect.isMainEffect() )
+ delete this.aStartedEffectIndexMap[ aEffect.getId() ];
+ }
+ }
+ else // there is no playing effect
{
- this.aEventMultiplexer.notifyRewindLastEffectEvent();
+ aEffect = this.aStartedEffectList.pop();
+ if( !aEffect.isMainEffect() )
+ delete this.aStartedEffectIndexMap[ aEffect.getId() ];
+ if( aEffect.isEnded() ) // Well that is almost an assertion.
+ {
+ if( aEffect.isMainEffect() )
+ {
+ this.aEventMultiplexer.notifyRewindLastEffectEvent();
+ if( this.nCurrentEffect > 0 )
+ --this.nCurrentEffect;
+ }
+ else
+ {
+ this.aEventMultiplexer.notifyRewindEndedInteractiveEffectEvent( aEffect.getId() );
+ }
+ }
+ this.update();
}
- if( this.nCurrentEffect > 0 )
- --this.nCurrentEffect;
- this.update();
+
this.bIsRewinding = false;
};
/** rewindToPreviousSlide
- * Displays the previous slide with all effects played.
+ * Displays the previous slide with all effects, that belong to the main
+ * animation sequence, played.
*
*/
SlideShow.prototype.rewindToPreviousSlide = function()
{
- if( this.isRunning() )
+ if( this.isAnyEffectPlaying() )
return;
var nNewSlide = nCurSlide - 1;
this.displaySlide( nNewSlide, true );
@@ -11739,16 +12065,16 @@ SlideShow.prototype.rewindToPreviousSlide = function()
*/
SlideShow.prototype.rewindAllEffects = function()
{
- if( this.nCurrentEffect == 0 )
+ if( !this.hasAnyEffectStarted() )
{
this.rewindToPreviousSlide();
return;
}
- while( this.nCurrentEffect > 0 )
- {
- this.rewindEffect();
- }
+ while( this.hasAnyEffectStarted() )
+ {
+ this.rewindEffect();
+ }
};
SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
commit c78e929b42e68d0ca21a1f9c5bb495ffbb716a6a
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Mon Jul 9 00:59:05 2012 +0200
Added support for interactive animation sequence to the JavaScript engine.
Now it is possible to start an effect by clicking on a given shape.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index a5a3a3f..cccbcd0 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -222,7 +222,7 @@ function getDefaultCharCodeDictionary()
}
-function slideOnMouseDown( aEvt )
+function slideOnMouseUp( aEvt )
{
if (!aEvt)
aEvt = window.event;
@@ -236,8 +236,12 @@ function slideOnMouseDown( aEvt )
if( 0 != nOffset )
dispatchEffects( nOffset );
+ return true; // the click has been handled
}
+document.handleClick = slideOnMouseUp;
+
+
/** Event handler for mouse wheel events in slide mode.
* based on http://adomas.org/javascript-mouse-wheel/
*
@@ -309,7 +313,7 @@ function mouseHandlerDispatch( aEvt, anAction )
}
//Set mouse event handler.
-document.onmousedown = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_DOWN ); };
+document.onmouseup = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_UP ); };
//document.onmousemove = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_MOVE ); };
/** Function to supply the default mouse handler dictionary.
@@ -324,13 +328,17 @@ function getDefaultMouseHandlerDictionary()
mouseHandlerDict[INDEX_MODE] = new Object();
// slide mode
- mouseHandlerDict[SLIDE_MODE][MOUSE_DOWN]
- = function( aEvt ) { return slideOnMouseDown( aEvt ); };
+ mouseHandlerDict[SLIDE_MODE][MOUSE_UP]
+ //= function( aEvt ) { return slideOnMouseDown( aEvt ); };
+ = function( aEvt ) { return ( aSlideShow.aEventMultiplexer ) ?
+ aSlideShow.aEventMultiplexer.notifyMouseClick( aEvt )
+ : slideOnMouseUp( aEvt ); };
+
mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL]
= function( aEvt ) { return slideOnMouseWheel( aEvt ); };
// index mode
- mouseHandlerDict[INDEX_MODE][MOUSE_DOWN]
+ mouseHandlerDict[INDEX_MODE][MOUSE_UP]
= function( aEvt ) { return toggleSlideIndex(); };
// mouseHandlerDict[INDEX_MODE][MOUSE_MOVE]
// = function( aEvt ) { return theSlideIndexPage.updateSelection( aEvt ); };
@@ -1433,7 +1441,7 @@ var NAVDBG = new DebugPrinter();
NAVDBG.off();
var ANIMDBG = new DebugPrinter();
-ANIMDBG.on();
+ANIMDBG.off();
var aRegisterEventDebugPrinter = new DebugPrinter();
aRegisterEventDebugPrinter.off();
@@ -5047,11 +5055,11 @@ NodeContext.prototype.makeSourceEventElement = function( sId, aEventBaseElem )
return null;
}
- if( !this.aAnimationNodeMap[ sId ] )
+ if( !this.aSourceEventElementMap[ sId ] )
{
- this.aAnimationNodeMap[ sId ] = new SourceEventElement( aEventBaseElem, this.aContext.aEventMultiplexer );
+ this.aSourceEventElementMap[ sId ] = new SourceEventElement( sId, aEventBaseElem, this.aContext.aEventMultiplexer );
}
- return this.aAnimationNodeMap[ sId ];
+ return this.aSourceEventElementMap[ sId ];
};
@@ -5323,7 +5331,7 @@ BaseNode.prototype.resolve = function()
{
this.aActivationEvent = makeDelay( bind( this, this.activate ), this.getBegin().getOffset() + this.nStartDelay );
}
- registerEvent( this.getBegin(), this.aActivationEvent, this.aNodeContext );
+ registerEvent( this.getId(), this.getBegin(), this.aActivationEvent, this.aNodeContext );
return true;
}
@@ -9378,6 +9386,7 @@ function SlideAnimations( aSlideShowContext )
this.aAnimatedElementMap = new Object();
this.aSourceEventElementMap = new Object();
this.aNextEffectEventArray = new NextEffectEventArray();
+ this.aInteractiveAnimationSequenceMap = new Object();
this.aEventMultiplexer = new EventMultiplexer( aSlideShowContext.aTimerEventQueue );
this.aRootNode = null;
this.bElementsParsed = false;
@@ -9385,6 +9394,11 @@ function SlideAnimations( aSlideShowContext )
this.aContext.aAnimationNodeMap = this.aAnimationNodeMap;
this.aContext.aAnimatedElementMap = this.aAnimatedElementMap;
this.aContext.aSourceEventElementMap = this.aSourceEventElementMap;
+
+ // We set up a low priority for the invocation of document.handleClick
+ // in order to make clicks on shapes, that start interactive animation
+ // sequence (on click), have an higher priority.
+ this.aEventMultiplexer.registerMouseClickHandler( document, 100 );
}
@@ -9433,7 +9447,12 @@ SlideAnimations.prototype.start = function()
if( !this.bElementsParsed )
return false;
- aSlideShow.setSlideEvents( this.aNextEffectEventArray, this.aEventMultiplexer );
+ this.chargeSourceEvents();
+ this.chargeInterAnimEvents();
+
+ aSlideShow.setSlideEvents( this.aNextEffectEventArray,
+ this.aInteractiveAnimationSequenceMap,
+ this.aEventMultiplexer );
if( this.aContext.bFirstRun == undefined )
this.aContext.bFirstRun = true;
@@ -9489,7 +9508,21 @@ SlideAnimations.prototype.clearNextEffectEvents = function()
this.aContext.bFirstRun = undefined;
};
+SlideAnimations.prototype.chargeSourceEvents = function()
+{
+ for( var id in this.aSourceEventElementMap )
+ {
+ this.aSourceEventElementMap[id].charge();
+ }
+};
+SlideAnimations.prototype.chargeInterAnimEvents = function()
+{
+ for( var id in this.aInteractiveAnimationSequenceMap )
+ {
+ this.aInteractiveAnimationSequenceMap[id].chargeEvents();
+ }
+};
/**********************************************************************************************
* Event classes and helper functions
@@ -9578,7 +9611,7 @@ function makeDelay( aFunctor, nTimeout )
// ------------------------------------------------------------------------------------------ //
-function registerEvent( aTiming, aEvent, aNodeContext )
+function registerEvent( nNodeId, aTiming, aEvent, aNodeContext )
{
var aSlideShowContext = aNodeContext.aContext;
var eTimingType = aTiming.getType();
@@ -9603,6 +9636,14 @@ function registerEvent( aTiming, aEvent, aNodeContext )
log( 'registerEvent: next effect event array not initialized' );
return;
}
+ var aInteractiveAnimationSequenceMap =
+ aSlideShowContext.aInteractiveAnimationSequenceMap;
+ if( !aInteractiveAnimationSequenceMap )
+ {
+ log( 'registerEvent: interactive animation sequence map not initialized' );
+ return;
+ }
+
switch( eTimingType )
{
case EVENT_TIMING:
@@ -9618,6 +9659,12 @@ function registerEvent( aTiming, aEvent, aNodeContext )
}
var aSourceEventElement = aNodeContext.makeSourceEventElement( sEventBaseElemId, aEventBaseElem );
+ if( !aInteractiveAnimationSequenceMap[ nNodeId ] )
+ {
+ var aInteractiveAnimationSequence = new InteractiveAnimationSequence( nNodeId );
+ aInteractiveAnimationSequenceMap[ nNodeId ] = aInteractiveAnimationSequence;
+ }
+
var bEventRegistered = false;
switch( eEventType )
{
@@ -9629,7 +9676,12 @@ function registerEvent( aTiming, aEvent, aNodeContext )
log( 'generateEvent: not handled event type: ' + eEventType );
}
if( bEventRegistered )
- aSourceEventElement.addEventListener( eEventType );
+ {
+ var aStartEvent = aInteractiveAnimationSequenceMap[ nNodeId ].getStartEvent();
+ var aEndEvent = aInteractiveAnimationSequenceMap[ nNodeId ].getEndEvent();
+ aEventMultiplexer.registerEvent( eEventType, aSourceEventElement.getId(), aStartEvent );
+ aEventMultiplexer.registerEvent( EVENT_TRIGGER_END_EVENT, nNodeId, aEndEvent );
+ }
}
else // no base event element present
{
@@ -9680,82 +9732,173 @@ registerEvent.DBG = function( aTiming, nTime )
// ------------------------------------------------------------------------------------------ //
-function SourceEventElement( aElement, aEventMultiplexer )
+function SourceEventElement( sId, aElement, aEventMultiplexer )
{
- this.nId = getUniqueId();
+ this.sId = sId;
this.aElement = aElement;
this.aEventMultiplexer = aEventMultiplexer;
- this.aEventListenerStateArray = new Array();
-}
+ this.aEventMultiplexer.registerMouseClickHandler( this, 1000 );
+
+ this.bClickHandled = false;
+ this.bIsPointerOver = false;
+ this.aElement.addEventListener( 'mouseover', bind2( SourceEventElement.prototype.onMouseEnter, this), false );
+ this.aElement.addEventListener( 'mouseout', bind2( SourceEventElement.prototype.onMouseLeave, this), false );
+}
SourceEventElement.prototype.getId = function()
{
- return this.nId;
+ return this.sId;
};
-SourceEventElement.prototype.isEqualTo = function( aSourceEventElement )
+SourceEventElement.prototype.onMouseEnter = function()
{
- return ( this.getId() == aSourceEventElement.getId() );
+ this.bIsPointerOver = true;
};
-SourceEventElement.prototype.onClick = function()
+SourceEventElement.prototype.onMouseLeave = function()
{
- this.aEventMultiplexer.notifyClickEvent( this );
+ this.bIsPointerOver = false;
};
-SourceEventElement.prototype.isEventListenerRegistered = function( eEventType )
+SourceEventElement.prototype.charge = function()
{
- return this.aEventListenerStateArray[ eEventType ];
+ this.bClickHandled = false;
};
-SourceEventElement.prototype.addEventListener = function( eEventType )
+SourceEventElement.prototype.handleClick = function( aMouseEvent )
{
- if( !this.aElement )
- return false;
+ if( !this.bIsPointerOver ) return false;
- this.aEventListenerStateArray[ eEventType ] = true;
- switch( eEventType )
- {
- case EVENT_TRIGGER_ON_CLICK:
- this.aElement.addEventListener( 'click', this.onClick, false );
- break;
- default:
- log( 'SourceEventElement.addEventListener: not handled event type: ' + eEventType );
- return false;
- }
+ if( this.bClickHandled )
+ return true;
+
+ this.aEventMultiplexer.notifyEvent( EVENT_TRIGGER_ON_CLICK, this.getId() );
+ aSlideShow.update();
+ this.bClickHandled = true;
return true;
};
-SourceEventElement.prototype.removeEventListener = function( eEventType )
+
+
+// ------------------------------------------------------------------------------------------ //
+function InteractiveAnimationSequence( nId )
{
- if( !this.aElement )
- return false;
+ this.nId = nId;
+ this.bIsRunning = false;
+ this.aStartEvent = null;
+ this.aEndEvent = null;
+}
- this.aEventListenerStateArray[ eEventType ] = false;
- switch( eEventType )
+InteractiveAnimationSequence.prototype.getId = function()
+{
+ return this.nId;
+};
+
+InteractiveAnimationSequence.prototype.getStartEvent = function()
+{
+ if( !this.aStartEvent )
{
- case EVENT_TRIGGER_ON_CLICK:
- this.aElement.removeEventListener( 'click', this.onClick, false );
- break;
- default:
- log( 'SourceEventElement.removeEventListener: not handled event type: ' + eEventType );
- return false;
+ this.aStartEvent =
+ makeEvent( bind2( InteractiveAnimationSequence.prototype.start, this ) );
}
- return true;
+ return this.aStartEvent;
};
+InteractiveAnimationSequence.prototype.getEndEvent = function()
+{
+ if( !this.aEndEvent )
+ {
+ this.aEndEvent =
+ makeEvent( bind2( InteractiveAnimationSequence.prototype.end, this ) );
+ }
+ return this.aEndEvent;
+};
+
+InteractiveAnimationSequence.prototype.chargeEvents = function()
+{
+ if( this.aStartEvent ) this.aStartEvent.charge();
+ if( this.aEndEvent ) this.aEndEvent.charge();
+};
+
+InteractiveAnimationSequence.prototype.isRunning = function()
+{
+ return this.bIsRunning;
+};
+
+InteractiveAnimationSequence.prototype.start = function()
+{
+ aSlideShow.notifyInteractiveAnimationSequenceStart( this.getId() );
+ this.bIsRunning = true;
+};
+
+InteractiveAnimationSequence.prototype.end = function()
+{
+ aSlideShow.notifyInteractiveAnimationSequenceEnd( this.getId() );
+ this.bIsRunning = false;
+};
+
+// ------------------------------------------------------------------------------------------ //
+/** class PriorityEntry
+ * It provides an entry type for priority queues.
+ * Higher is the value of nPriority higher is the priority of the created entry.
+ *
+ * @param aValue
+ * The object to be prioritized.
+ * @param nPriority
+ * An integral number representing the object priority.
+ *
+ */
+function PriorityEntry( aValue, nPriority )
+{
+ this.aValue = aValue;
+ this.nPriority = nPriority;
+}
+
+/** EventEntry.compare
+ * Compare priority of two entries.
+ *
+ * @param aLhsEntry
+ * An instance of type PriorityEntry.
+ * @param aRhsEntry
+ * An instance of type PriorityEntry.
+ * @return {Boolean}
+ * True if the first entry has higher priority of the second entry,
+ * false otherwise.
+ */
+PriorityEntry.compare = function( aLhsEntry, aRhsEntry )
+{
+ return ( aLhsEntry.nPriority < aRhsEntry.nPriority );
+};
// ------------------------------------------------------------------------------------------ //
function EventMultiplexer( aTimerEventQueue )
{
this.aTimerEventQueue = aTimerEventQueue;
this.aEventMap = new Object();
+ this.aMouseClickHandlerSet = new PriorityQueue( PriorityEntry.compare );
this.aSkipEffectEvent = null;
this.aRewindCurrentEffectEvent = null;
this.aRewindLastEffectEvent = null;
}
+EventMultiplexer.prototype.registerMouseClickHandler = function( aHandler, nPriority )
+{
+ var aHandlerEntry = new PriorityEntry( aHandler, nPriority );
+ this.aMouseClickHandlerSet.push( aHandlerEntry );
+};
+
+EventMultiplexer.prototype.notifyMouseClick = function( aMouseEvent )
+{
+ var aMouseClickHandlerSet = this.aMouseClickHandlerSet;
+ var nSize = aMouseClickHandlerSet.size();
+ for( var i = 0; i < nSize; ++i )
+ {
+ var aHandlerEntry = aMouseClickHandlerSet.aSequence[i];
+ if( aHandlerEntry.aValue.handleClick( aMouseEvent ) )
+ break;
+ }
+};
EventMultiplexer.prototype.registerEvent = function( eEventType, aNotifierId, aEvent )
{
@@ -11284,12 +11427,17 @@ function SlideShow()
this.aTimerEventQueue = new TimerEventQueue( this.aTimer );
this.aActivityQueue = new ActivityQueue( this.aTimer );
this.aNextEffectEventArray = null;
+ this.aInteractiveAnimationSequenceMap = null;
this.aEventMultiplexer = null;
- this.aContext = new SlideShowContext( this.aTimerEventQueue, this.aEventMultiplexer,
- this.aNextEffectEventArray, this.aActivityQueue );
+ this.aContext = new SlideShowContext( this.aTimerEventQueue,
+ this.aEventMultiplexer,
+ this.aNextEffectEventArray,
+ this.aInteractiveAnimationSequenceMap,
+ this.aActivityQueue );
this.nCurrentEffect = 0;
this.eDirection = FORWARD;
+ this.nTotalInteracAnimSeqRunning = 0;
this.bIsIdle = true;
this.bIsEnabled = true;
this.bIsRewinding = false;
@@ -11299,19 +11447,27 @@ function SlideShow()
}
-SlideShow.prototype.setSlideEvents = function( aNextEffectEventArray, aEventMultiplexer )
+SlideShow.prototype.setSlideEvents = function( aNextEffectEventArray,
+ aInteractiveAnimationSequenceMap,
+ aEventMultiplexer )
{
if( !aNextEffectEventArray )
log( 'SlideShow.setSlideEvents: aNextEffectEventArray is not valid' );
+ if( !aInteractiveAnimationSequenceMap )
+ log( 'SlideShow.setSlideEvents:aInteractiveAnimationSequenceMap is not valid' );
+
if( !aEventMultiplexer )
log( 'SlideShow.setSlideEvents: aEventMultiplexer is not valid' );
this.aContext.aNextEffectEventArray = aNextEffectEventArray;
this.aNextEffectEventArray = aNextEffectEventArray;
+ this.aContext.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap;
+ this.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap;
this.aContext.aEventMultiplexer = aEventMultiplexer;
this.aEventMultiplexer = aEventMultiplexer;
this.nCurrentEffect = 0;
+ this.nTotalInteracAnimSeqRunning = 0;
};
SlideShow.prototype.createSlideTransition = function( aSlideTransitionHandler, aLeavingSlide, aEnteringSlide, aTransitionEndEvent )
@@ -11361,6 +11517,11 @@ SlideShow.prototype.isRunning = function()
return !this.bIsIdle;
};
+SlideShow.prototype.isInterAnimSeqRunning = function()
+{
+ return ( this.nTotalInteracAnimSeqRunning > 0 );
+};
+
SlideShow.prototype.isEnabled = function()
{
return this.bIsEnabled;
@@ -11393,11 +11554,27 @@ SlideShow.prototype.notifyTransitionEnd = function( nSlideIndex )
}
};
+SlideShow.prototype.notifyInteractiveAnimationSequenceStart = function( nNodeId )
+{
+ ++this.nTotalInteracAnimSeqRunning;
+};
+
+SlideShow.prototype.notifyInteractiveAnimationSequenceEnd = function( nNodeId )
+{
+ assert( this.nTotalInteracAnimSeqRunning > 0,
+ 'SlideShow.notifyInteractiveAnimationSequenceStart: ' +
+ 'the total number of running interactive application is zero' );
+ --this.nTotalInteracAnimSeqRunning;
+};
+
SlideShow.prototype.nextEffect = function()
{
if( !this.isEnabled() )
return false;
+ if( this.isInterAnimSeqRunning() )
+ return true;
+
if( this.isRunning() )
{
this.skipCurrentEffect();
@@ -11443,6 +11620,9 @@ SlideShow.prototype.skipEffect = function()
if( this.bIsSkipping || this.bIsRewinding )
return true;
+ if( this.isInterAnimSeqRunning() )
+ return true;
+
if( this.isRunning() )
{
this.skipCurrentEffect();
@@ -11478,6 +11658,9 @@ SlideShow.prototype.skipAllEffects = function()
if( this.bIsSkippingAll )
return true;
+ if( this.isInterAnimSeqRunning() )
+ return true;
+
this.bIsSkippingAll = true;
if( this.isRunning() )
{
@@ -11513,6 +11696,9 @@ SlideShow.prototype.rewindEffect = function()
if( this.bIsSkipping || this.bIsRewinding )
return;
+ if( this.isInterAnimSeqRunning() )
+ return true;
+
if( this.nCurrentEffect == 0 )
{
this.rewindToPreviousSlide();
@@ -11717,11 +11903,12 @@ var aSlideShow = null;
// ------------------------------------------------------------------------------------------ //
-function SlideShowContext( aTimerEventQueue, aEventMultiplexer, aNextEffectEventArray, aActivityQueue)
+function SlideShowContext( aTimerEventQueue, aEventMultiplexer, aNextEffectEventArray, aInteractiveAnimationSequenceMap, aActivityQueue)
{
this.aTimerEventQueue = aTimerEventQueue;
this.aEventMultiplexer = aEventMultiplexer;
this.aNextEffectEventArray = aNextEffectEventArray;
+ this.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap;
this.aActivityQueue = aActivityQueue;
this.bIsSkipping = false;
}
commit ada5f5f507b2816b32280742e16d9e54d4b10b98
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Thu Jul 5 19:17:26 2012 +0200
Bug fix: now the JavaScript engine parse the âcounter-clockwiseâ value correctly.
Previously it expected âcounterclockwiseâ.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 984eaef..a5a3a3f 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -4117,9 +4117,9 @@ aColorSpaceOutMap = [ 'rgb', 'hsl' ];
var CLOCKWISE = 0;
var COUNTERCLOCKWISE = 1;
-aClockDirectionInMap = { 'clockwise': CLOCKWISE, 'counterclockwise': COUNTERCLOCKWISE };
+aClockDirectionInMap = { 'clockwise': CLOCKWISE, 'counter-clockwise': COUNTERCLOCKWISE };
-aClockDirectionOutMap = [ 'clockwise', 'counterclockwise' ];
+aClockDirectionOutMap = [ 'clockwise', 'counter-clockwise' ];
// Attribute Value Types
commit b0b7d169a062bf5c3e8b51d85620acce0b546086
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Thu Jul 5 18:50:39 2012 +0200
Bug fix: now the darken and lighten effects work in the right way.
Edited the effects.xml and changed effect direction to counterclockwise.
diff --git a/sd/xml/effects.xml b/sd/xml/effects.xml
index be341ef..b555a32 100644
--- a/sd/xml/effects.xml
+++ b/sd/xml/effects.xml
@@ -1172,9 +1172,9 @@
<anim:par smil:begin="indefinite" smil:fill="hold">
<anim:par smil:begin="0" smil:fill="hold">
<anim:par smil:begin="0" smil:fill="hold" pres:node-type="on-click" pres:preset-class="emphasis" pres:preset-id="ooo-emphasis-darken">
- <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/>
- <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="fill-color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/>
- <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="stroke-color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/>
+ <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/>
+ <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="fill-color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/>
+ <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="stroke-color" smil:by="hsl(0,-12%,-25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/>
<anim:set smil:dur="0.5" smil:fill="hold" smil:attributeName="fill" smil:to="solid"/>
</anim:par>
</anim:par>
@@ -1200,9 +1200,9 @@
<anim:par smil:begin="indefinite" smil:fill="hold">
<anim:par smil:begin="0" smil:fill="hold">
<anim:par smil:begin="0" smil:fill="hold" pres:node-type="on-click" pres:preset-class="emphasis" pres:preset-id="ooo-emphasis-lighten">
- <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/>
- <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="fill-color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/>
- <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="stroke-color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="clockwise"/>
+ <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/>
+ <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="fill-color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/>
+ <anim:animateColor smil:dur="0.5" smil:fill="hold" smil:attributeName="stroke-color" smil:by="hsl(0,12%,25%)" anim:color-interpolation="hsl" anim:color-interpolation-direction="counterclockwise"/>
<anim:set smil:dur="0.5" smil:fill="hold" smil:attributeName="fill" smil:to="solid"/>
</anim:par>
</anim:par>
commit aa50b3bd6b1282e6dff621df14997911b7a1f10f
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Thu Jul 5 16:35:02 2012 +0200
Bug fix: now repeated animations and begin=âafter effect â works properly together.
Modified the CustomAnimationEffect class in order to take into account the repeatCount
attribute value when computing the node effect absolute duration.
diff --git a/sd/source/core/CustomAnimationEffect.cxx b/sd/source/core/CustomAnimationEffect.cxx
index 2ed6115..65fbb4a 100644
--- a/sd/source/core/CustomAnimationEffect.cxx
+++ b/sd/source/core/CustomAnimationEffect.cxx
@@ -281,6 +281,10 @@ void CustomAnimationEffect::setNode( const ::com::sun::star::uno::Reference< ::c
}
mfAbsoluteDuration = mfDuration;
+ double fRepeatCount = 1.0;
+ if( (mxNode->getRepeatCount()) >>= fRepeatCount )
+ mfAbsoluteDuration *= fRepeatCount;
+
checkForText();
}
@@ -755,7 +759,9 @@ void CustomAnimationEffect::setDuration( double fDuration )
{
double fScale = fDuration / mfDuration;
mfDuration = fDuration;
- mfAbsoluteDuration = mfDuration;
+ double fRepeatCount = 1.0;
+ getRepeatCount() >>= fRepeatCount;
+ mfAbsoluteDuration = mfDuration * fRepeatCount;
// calculate effect duration and get target shape
Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY );
@@ -954,7 +960,12 @@ sal_Int16 CustomAnimationEffect::getFill() const
void CustomAnimationEffect::setRepeatCount( const Any& rRepeatCount )
{
if( mxNode.is() )
+ {
mxNode->setRepeatCount( rRepeatCount );
+ double fRepeatCount = 1.0;
+ rRepeatCount >>= fRepeatCount;
+ mfAbsoluteDuration = mfDuration * fRepeatCount;
+ }
}
// --------------------------------------------------------------------
commit c1598303e4c458795c28d41408a00d2082396113
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Thu Jul 5 10:19:47 2012 +0200
Bug fix: now a clip-based transition works correctly when mode=âoutâ and reverse method involves flipping.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index f042263..984eaef 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -7933,8 +7933,10 @@ ClippingFunctor.prototype.perform = function( nT, nWidth, nHeight )
{
var aClipPoly = this.aParametricPolyPolygon.perform( this.bForwardParameterSweep ? nT : (1 - nT) );
- if( this.bFlip )
- aClipPoly.changeOrientation();
+ // Note: even if the reverse method involves flipping we don't need to
+ // change the clip-poly orientation because we utilize the 'nonzero'
+ // clip-rule.
+ // See: http://www.w3.org/TR/SVG11/painting.html#FillRuleProperty
if( this.bSubtractPolygon )
{
commit aaed0c6e4953941c232cb17fcedda92635ec5905
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Wed Jul 4 18:50:46 2012 +0200
Provided support for rewinding to the previous slide and for skipping / rewinding all effects.
The following method of the SlideShow class has been implemented:
skipAllEffects, rewindToPreviousSlide, rewindAllEffects.
Commented out the calls to the initAnimatedElement methods for ValueListActivity and
FromToByActivity class as it is the source of a bug.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 2e66561..f042263 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -150,13 +150,13 @@ function getDefaultKeyCodeDictionary()
keyCodeDict[SLIDE_MODE][RIGHT_KEY]
= function() { return dispatchEffects(1); };
keyCodeDict[SLIDE_MODE][UP_KEY]
- = function() { return skipEffects(-1); };
+ = function() { return aSlideShow.rewindEffect(); };
keyCodeDict[SLIDE_MODE][DOWN_KEY]
= function() { return skipEffects(1); };
keyCodeDict[SLIDE_MODE][PAGE_UP_KEY]
- = function() { return switchSlide( -1, true ); };
+ = function() { return aSlideShow.rewindAllEffects(); };
keyCodeDict[SLIDE_MODE][PAGE_DOWN_KEY]
- = function() { return switchSlide( 1, true ); };
+ = function() { return skipAllEffects(); };
keyCodeDict[SLIDE_MODE][HOME_KEY]
= function() { return aSlideShow.displaySlide( 0, true ); };
keyCodeDict[SLIDE_MODE][END_KEY]
@@ -1433,7 +1433,7 @@ var NAVDBG = new DebugPrinter();
NAVDBG.off();
var ANIMDBG = new DebugPrinter();
-ANIMDBG.off();
+ANIMDBG.on();
var aRegisterEventDebugPrinter = new DebugPrinter();
aRegisterEventDebugPrinter.off();
@@ -2985,6 +2985,15 @@ function dispatchEffects(dir)
}
}
+function skipAllEffects()
+{
+ var bRet = aSlideShow.skipAllEffects();
+ if( !bRet )
+ {
+ switchSlide( 1, true );
+ }
+}
+
function skipEffects(dir)
{
if( dir == 1 )
@@ -2993,12 +3002,12 @@ function skipEffects(dir)
if( !bRet )
{
- switchSlide( 1, false );
+ switchSlide( 1, true );
}
}
else
{
- switchSlide( dir, false );
+ switchSlide( dir, true );
}
}
@@ -10725,7 +10734,7 @@ function FromToByActivityTemplate( BaseType ) // template parameter
this.nIteration = 0;
this.bCumulative = bAccumulate;
- this.initAnimatedElement();
+ //this.initAnimatedElement();
}
extend( FromToByActivity, BaseType );
@@ -10931,7 +10940,7 @@ function ValueListActivityTemplate( BaseType ) // template parameter
this.bCumulative = bAccumulate;
this.aLastValue = this.aValueList[ this.aValueList.length - 1 ];
- this.initAnimatedElement();
+ //this.initAnimatedElement();
}
extend( ValueListActivity, BaseType );
@@ -10943,7 +10952,7 @@ function ValueListActivityTemplate( BaseType ) // template parameter
ANIMDBG.print( 'createValueListActivity: value[' + i + '] = ' + this.aValueList[i] );
}
- this.initAnimatedElement();
+ //this.initAnimatedElement();
};
ValueListActivity.prototype.initAnimatedElement = function()
@@ -11283,6 +11292,7 @@ function SlideShow()
this.bIsEnabled = true;
this.bIsRewinding = false;
this.bIsSkipping = false;
+ this.bIsSkippingAll = false;
this.bNoSlideTransition = false;
}
@@ -11422,30 +11432,6 @@ SlideShow.prototype.skipCurrentEffect = function()
this.bIsSkipping = false;
};
-/** rewindEffect
- * Rewind the current playing effect or the last played one.
- *
- */
-SlideShow.prototype.rewindEffect = function()
-{
- if( this.bIsSkipping || this.bIsRewinding )
- return true;
-
- this.bIsRewinding = true;
- if( this.isRunning() )
- {
- this.aEventMultiplexer.notifyRewindCurrentEffectEvent();
- }
- else
- {
- this.aEventMultiplexer.notifyRewindLastEffectEvent();
- }
- if( this.nCurrentEffect > 0 )
- --this.nCurrentEffect;
- this.update();
- this.bIsRewinding = false;
-};
-
/** skipEffect
* Skip the next effect to be played.
*
@@ -11478,6 +11464,105 @@ SlideShow.prototype.skipEffect = function()
return true;
};
+/** skipAllEffects
+ * Skip all left effects on the current slide.
+ *
+ * @return {Boolean}
+ * True if it already skipping or when it has ended skipping,
+ * false if the next slide needs to be displayed.
+ */
+SlideShow.prototype.skipAllEffects = function()
+{
+ if( this.bIsSkippingAll )
+ return true;
+
+ this.bIsSkippingAll = true;
+ if( this.isRunning() )
+ {
+ this.skipCurrentEffect();
+ }
+ else if( !this.aNextEffectEventArray
+ || ( this.nCurrentEffect >= this.aNextEffectEventArray.size() ) )
+ {
+ this.bIsSkippingAll = false;
+ return false;
+ }
+
+ // Pay attention here: a new next effect event is appended to
+ // aNextEffectEventArray only after the related animation node has been
+ // resolved, that is only after the animation node related to the previous
+ // effect has notified to be deactivated to the main sequence time container.
+ // So you should avoid any optimization here because the size of
+ // aNextEffectEventArray will going on increasing after every skip action.
+ while( this.nCurrentEffect < this.aNextEffectEventArray.size() )
+ {
+ this.skipEffect();
+ }
+ this.bIsSkippingAll = false;
+ return true;
+};
+
+/** rewindEffect
+ * Rewind the current playing effect or the last played one.
+ *
+ */
+SlideShow.prototype.rewindEffect = function()
+{
+ if( this.bIsSkipping || this.bIsRewinding )
+ return;
+
+ if( this.nCurrentEffect == 0 )
+ {
+ this.rewindToPreviousSlide();
+ return;
+ }
+
+ this.bIsRewinding = true;
+ if( this.isRunning() )
+ {
+ this.aEventMultiplexer.notifyRewindCurrentEffectEvent();
+ }
+ else
+ {
+ this.aEventMultiplexer.notifyRewindLastEffectEvent();
+ }
+ if( this.nCurrentEffect > 0 )
+ --this.nCurrentEffect;
+ this.update();
+ this.bIsRewinding = false;
+};
+
+/** rewindToPreviousSlide
+ * Displays the previous slide with all effects played.
+ *
+ */
+SlideShow.prototype.rewindToPreviousSlide = function()
+{
+ if( this.isRunning() )
+ return;
+ var nNewSlide = nCurSlide - 1;
+ this.displaySlide( nNewSlide, true );
+ this.skipAllEffects();
+};
+
+/** rewindAllEffects
+ * Rewind all effects already played on the current slide.
+ *
+ */
+SlideShow.prototype.rewindAllEffects = function()
+{
+ if( this.nCurrentEffect == 0 )
+ {
+ this.rewindToPreviousSlide();
+ return;
+ }
+
+ while( this.nCurrentEffect > 0 )
+ {
+ this.rewindEffect();
+ }
+};
+
SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
{
var aMetaDoc = theMetaDoc;
commit 9a786c8a1b76277e1926b19de9fc5732ae183a02
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Tue Jul 3 19:22:34 2012 +0200
Performed some clean up and added documentation comments.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 9b62dd7..2e66561 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -6281,6 +6281,7 @@ BaseContainerNode.prototype.removeEffect = function()
var nChildrenCount = this.aChildrenArray.length;
if( nChildrenCount == 0 )
return;
+ // We remove effect in reverse order.
for( var i = nChildrenCount - 1; i >= 0; --i )
{
if( ( this.aChildrenArray[i].getState() & ( FROZEN_NODE | ENDED_NODE ) ) == 0 )
@@ -6465,11 +6466,24 @@ SequentialTimeContainer.prototype.notifyDeactivating = function( aNotifier )
}
};
+/** skipEffect
+ * Skip the current playing shape effect.
+ * Requires: the current node is the main sequence root node.
+ *
+ * @param aChildNode
+ * An animation node representing the root node of the shape effect being
+ * played.
+ */
SequentialTimeContainer.prototype.skipEffect = function( aChildNode )
{
if( this.isChildNode( aChildNode ) )
{
+ // First off we end all queued activities.
this.getContext().aActivityQueue.endAll();
+ // We signal that we are going to skip all subsequent animations by
+ // setting the bIsSkipping flag to 'true', then all queued events are
+ // fired immediately. In such a way the correct order of the various
+ // events that belong to the animation time-line is preserved.
this.getContext().bIsSkipping = true;
this.getContext().aTimerEventQueue.forceEmpty();
this.getContext().bIsSkipping = false;
@@ -6478,63 +6492,122 @@ SequentialTimeContainer.prototype.skipEffect = function( aChildNode )
}
else
{
- log( 'SequentialTimeContainer.skipEffect: unknown child: ' + aChildNode.getId() );
+ log( 'SequentialTimeContainer.skipEffect: unknown child: '
+ + aChildNode.getId() );
}
};
+/** rewindCurrentEffect
+ * Rewind a playing shape effect.
+ * Requires: the current node is the main sequence root node.
+ *
+ * @param aChildNode
+ * An animation node representing the root node of the shape effect being
+ * played
+ */
SequentialTimeContainer.prototype.rewindCurrentEffect = function( aChildNode )
{
if( this.isChildNode( aChildNode ) )
{
- assert( !this.bIsRewinding, 'SequentialTimeContainer.rewindCurrentEffect: is already rewinding.' );
+ assert( !this.bIsRewinding,
+ 'SequentialTimeContainer.rewindCurrentEffect: is already rewinding.' );
+ // We signal we are rewinding so the notifyDeactivating method returns
+ // immediately without increment the finished children counter and
+ // resolve the next child.
this.bIsRewinding = true;
+ // First off we end all queued activities.
this.getContext().aActivityQueue.endAll();
+ // We signal that we are going to skip all subsequent animations by
+ // setting the bIsSkipping flag to 'true', then all queued events are
+ // fired immediately. In such a way the correct order of the various
+ // events that belong to the animation time-line is preserved.
this.getContext().bIsSkipping = true;
this.getContext().aTimerEventQueue.forceEmpty();
this.getContext().bIsSkipping = false;
+ // We end all new activities appended to the activity queue by
+ // the fired events.
this.getContext().aActivityQueue.endAll();
+ // Now we perform a final 'end' and restore the animated shape to
+ // the state it was before the current effect was applied.
aChildNode.end();
aChildNode.removeEffect();
+ // Finally we place the child node to the 'unresolved' state and
+ // resolve it again.
aChildNode.init();
this.resolveChild( aChildNode );
this.bIsRewinding = false;
}
else
{
- log( 'SequentialTimeContainer.rewindCurrentEffect: unknown child: ' + aChildNode.getId() );
+ log( 'SequentialTimeContainer.rewindCurrentEffect: unknown child: '
+ + aChildNode.getId() );
}
};
+/** rewindLastEffect
+ * Rewind the last ended effect.
+ * Requires: the current node is the main sequence root node.
+ *
+ * @param aChildNode
+ * An animation node representing the root node of the next shape effect
+ * to be played.
+ */
SequentialTimeContainer.prototype.rewindLastEffect = function( aChildNode )
{
if( this.isChildNode( aChildNode ) )
{
- assert( !this.bIsRewinding, 'SequentialTimeContainer.rewindLastEffect: is already rewinding.' );
+ assert( !this.bIsRewinding,
+ 'SequentialTimeContainer.rewindLastEffect: is already rewinding.' );
+ // We signal we are rewinding so the notifyDeactivating method returns
+ // immediately without increment the finished children counter and
+ // resolve the next child.
this.bIsRewinding = true;
+ // We end the current effect and remove any change it applies on the
+ // animated shape.
this.getContext().aTimerEventQueue.forceEmpty();
this.getContext().aActivityQueue.clear();
-
aChildNode.end();
aChildNode.removeEffect();
+
+ // As we rewind the previous effect we need to decrease the finished
+ // children counter.
--this.nFinishedChildren;
var aPreviousChildNode = this.aChildrenArray[ this.nFinishedChildren ];
+ // No need to invoke the end method for the previous child as it is
+ // already in the ENDED state.
+
aPreviousChildNode.removeEffect();
+ // We place the child node to the 'unresolved' state.
aPreviousChildNode.init();
- // We need to re-initialize it too, because it is in state ENDED now,
- // and cannot be resolved again later.
+ // We need to re-initialize the old current child too, because it is
+ // in ENDED state now, On the contrary it cannot be resolved again later.
aChildNode.init();
this.resolveChild( aPreviousChildNode );
this.bIsRewinding = false;
}
else
{
- log( 'SequentialTimeContainer.rewindLastEffect: unknown child: ' + aChildNode.getId() );
+ log( 'SequentialTimeContainer.rewindLastEffect: unknown child: '
+ + aChildNode.getId() );
}
};
+/** resolveChild
+ * Resolve the passed child.
+ * In case this node is a main sequence root node events for skipping and
+ * rewinding the effect related to the passed child node are created and
+ * registered.
+ *
+ * @param aChildNode
+ * An animation node representing the root node of the next shape effect
+ * to be played.
+ * @return
+ * It returns true if the passed child has been resolved successfully,
+ * false otherwise.
+ */
SequentialTimeContainer.prototype.resolveChild = function( aChildNode )
{
var bResolved = aChildNode.resolve();
@@ -6551,7 +6624,7 @@ SequentialTimeContainer.prototype.resolveChild = function( aChildNode )
this.aRewindCurrentEffectEvent.dispose();
this.aRewindCurrentEffectEvent = makeEvent( bind2( SequentialTimeContainer.prototype.rewindCurrentEffect, this, aChildNode ) );
- this.aContext.aEventMultiplexer.registerRewindEffectEvent( this.aRewindCurrentEffectEvent );
+ this.aContext.aEventMultiplexer.registerRewindCurrentEffectEvent( this.aRewindCurrentEffectEvent );
if( this.aRewindLastEffectEvent )
this.aRewindLastEffectEvent.dispose();
@@ -8529,11 +8602,6 @@ AnimatedElement.prototype.getId = function()
return this.aActiveElement.getAttribute( 'id' );
};
-AnimatedElement.prototype.isUpdated = function()
-{
- return this.bIsUpdated;
-};
-
AnimatedElement.prototype.getAdditiveMode = function()
{
return this.eAdditiveMode;
@@ -8571,8 +8639,7 @@ AnimatedElement.prototype.notifySlideStart = function()
AnimatedElement.prototype.notifyAnimationStart = function()
{
- this.DBG( '.notifyAnimationStart invoked' );
- this.bIsUpdated = false;
+ // empty body
};
AnimatedElement.prototype.notifyAnimationEnd = function()
@@ -8582,28 +8649,16 @@ AnimatedElement.prototype.notifyAnimationEnd = function()
AnimatedElement.prototype.notifyNextEffectStart = function( nEffectIndex )
{
-// assert( this.nCurrentState === nEffectIndex,
-// 'AnimatedElement(' + this.getId() + ').notifyNextEffectStart: assertion (current state == effect index) failed' );
-//
-// if( this.isUpdated() )
-// {
-// if( !this.aElementArray[ nEffectIndex ] )
-// {
-// this.aElementArray[ nEffectIndex ] = this.aElementArray[ this.nCurrentState ];
-// this.DBG( '.notifyNextEffectStart(' + nEffectIndex + '): new state set to previous one ' );
-// }
-// }
-// else
-// {
-// if( !this.aElementArray[ nEffectIndex ] )
-// {
-// this.aElementArray[ nEffectIndex ] = this.aActiveElement.cloneNode( true );
-// this.DBG( '.notifyNextEffectStart(' + nEffectIndex + '): cloned active state ' );
-// }
-// }
-// ++this.nCurrentState;
+ // empty body
};
+/** saveState
+ * Save the state of the managed animated element and append it to aStateSet
+ * using the passed animation node id as key.
+ *
+ * @param nAnimationNodeId
+ * A non negative integer representing the unique id of an animation node.
+ */
AnimatedElement.prototype.saveState = function( nAnimationNodeId )
{
ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').saveState(' + nAnimationNodeId +')' );
@@ -8620,6 +8675,16 @@ AnimatedElement.prototype.saveState = function( nAnimationNodeId )
};
+/** restoreState
+ * Restore the state of the managed animated element to the state with key
+ * the passed animation node id.
+ *
+ * @param nAnimationNodeId
+ * A non negative integer representing the unique id of an animation node.
+ *
+ * @return
+ * True if the restoring operation is successful, false otherwise.
+ */
AnimatedElement.prototype.restoreState = function( nAnimationNodeId )
{
if( !this.aStateSet[ nAnimationNodeId ] )
@@ -9676,7 +9741,7 @@ function EventMultiplexer( aTimerEventQueue )
this.aTimerEventQueue = aTimerEventQueue;
this.aEventMap = new Object();
this.aSkipEffectEvent = null;
- this.aRewindEffectEvent = null;
+ this.aRewindCurrentEffectEvent = null;
this.aRewindLastEffectEvent = null;
}
@@ -9727,17 +9792,17 @@ EventMultiplexer.prototype.notifySkipEffectEvent = function()
}
};
-EventMultiplexer.prototype.registerRewindEffectEvent = function( aEvent )
+EventMultiplexer.prototype.registerRewindCurrentEffectEvent = function( aEvent )
{
- this.aRewindEffectEvent = aEvent;
+ this.aRewindCurrentEffectEvent = aEvent;
};
-EventMultiplexer.prototype.notifyRewindEffectEvent = function()
+EventMultiplexer.prototype.notifyRewindCurrentEffectEvent = function()
{
- if( this.aRewindEffectEvent )
+ if( this.aRewindCurrentEffectEvent )
{
- this.aTimerEventQueue.addEvent( this.aRewindEffectEvent );
- this.aRewindEffectEvent = null;
+ this.aTimerEventQueue.addEvent( this.aRewindCurrentEffectEvent );
+ this.aRewindCurrentEffectEvent = null;
}
};
@@ -11342,6 +11407,10 @@ SlideShow.prototype.nextEffect = function()
return true;
};
+/** skipCurrentEffect
+ * Skip the current playing effect.
+ *
+ */
SlideShow.prototype.skipCurrentEffect = function()
{
if( this.bIsSkipping || this.bIsRewinding )
@@ -11353,6 +11422,10 @@ SlideShow.prototype.skipCurrentEffect = function()
this.bIsSkipping = false;
};
+/** rewindEffect
+ * Rewind the current playing effect or the last played one.
+ *
+ */
SlideShow.prototype.rewindEffect = function()
{
if( this.bIsSkipping || this.bIsRewinding )
@@ -11361,17 +11434,22 @@ SlideShow.prototype.rewindEffect = function()
this.bIsRewinding = true;
if( this.isRunning() )
{
- this.aEventMultiplexer.notifyRewindEffectEvent();
+ this.aEventMultiplexer.notifyRewindCurrentEffectEvent();
}
else
{
this.aEventMultiplexer.notifyRewindLastEffectEvent();
}
- --this.nCurrentEffect;
+ if( this.nCurrentEffect > 0 )
+ --this.nCurrentEffect;
this.update();
this.bIsRewinding = false;
};
+/** skipEffect
+ * Skip the next effect to be played.
+ *
+ */
SlideShow.prototype.skipEffect = function()
{
if( this.bIsSkipping || this.bIsRewinding )
@@ -11400,16 +11478,6 @@ SlideShow.prototype.skipEffect = function()
return true;
};
-//SlideShow.prototype.previousEffect = function()
-//{
-// if( this.nCurrentEffect <= 0 )
-// return false;
-// this.eDirection = BACKWARD;
-// this.aNextEffectEventArray.at( this.nCurrentEffect ).fire();
-// --this.nCurrentEffect;
-// return true;
-//};
-
SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
{
var aMetaDoc = theMetaDoc;
commit de912929b54d8b4ab1898a8f011233c340c2e080
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Tue Jul 3 15:39:32 2012 +0200
Changed the rewindCurrentEffect method.
The change was needed because rewinding a playing shape transition effect based on
a clip-path doesnât work properly on Firefox and Internet Explorer.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index d705658..9b62dd7 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -6489,8 +6489,11 @@ SequentialTimeContainer.prototype.rewindCurrentEffect = function( aChildNode )
assert( !this.bIsRewinding, 'SequentialTimeContainer.rewindCurrentEffect: is already rewinding.' );
this.bIsRewinding = true;
+ this.getContext().aActivityQueue.endAll();
+ this.getContext().bIsSkipping = true;
this.getContext().aTimerEventQueue.forceEmpty();
- this.getContext().aActivityQueue.clear();
+ this.getContext().bIsSkipping = false;
+ this.getContext().aActivityQueue.endAll();
aChildNode.end();
aChildNode.removeEffect();
commit ce5a16c4e34f50f101ec25839686f28feca42aa8
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Mon Jul 2 23:36:35 2012 +0200
Skipping a single effect works in JavaScript even if the effect is rewinded (fill=remove).
Added a bIsSkipping flag to the SlideShowContext class and modified the activate_st method
of the AnimationBaseNode class. Now when we are skipping the managed activity is
not appended to the activity class but the end method is executed immediately.
In such a way the correct order of the various events that belong to the animation time-line
is preserved.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index c71cad6..d705658 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -5745,7 +5745,14 @@ AnimationBaseNode.prototype.activate_st = function()
{
this.saveStateOfAnimatedElement();
this.aActivity.setTargets( this.getAnimatedElement() );
- this.getContext().aActivityQueue.addActivity( this.aActivity );
+ if( this.getContext().bIsSkipping )
+ {
+ this.aActivity.end();
+ }
+ else
+ {
+ this.getContext().aActivityQueue.addActivity( this.aActivity );
+ }
}
else
{
@@ -5821,8 +5828,7 @@ AnimationBaseNode.prototype.saveStateOfAnimatedElement = function()
AnimationBaseNode.prototype.removeEffect = function()
{
- log( 'AnimationBaseNode.removeEffect invoked' );
- this.getAnimatedElement().setTo( this.getId() );
+ this.getAnimatedElement().restoreState( this.getId() );
};
AnimationBaseNode.prototype.getTargetElement = function()
@@ -6175,7 +6181,7 @@ BaseContainerNode.prototype.deactivate_st = function( eDestState )
// end all children that are not ENDED:
this.forEachChildNode( mem_fn( 'end' ), ~ENDED_NODE );
if( this.getFillMode() == FILL_MODE_REMOVE )
- this.forEachChildNode( mem_fn( 'removeEffect' ), ENDED_NODE );
+ this.removeEffect();
}
};
@@ -6277,8 +6283,14 @@ BaseContainerNode.prototype.removeEffect = function()
return;
for( var i = nChildrenCount - 1; i >= 0; --i )
{
- if( ( this.aChildrenArray[i].getState() & FROZEN_NODE | ENDED_NODE ) == 0 )
+ if( ( this.aChildrenArray[i].getState() & ( FROZEN_NODE | ENDED_NODE ) ) == 0 )
+ {
+ log( 'BaseContainerNode.removeEffect: child(id:'
+ + this.aChildrenArray[i].getId() + ') is neither frozen nor ended;'
+ + ' state: '
+ + aTransitionModeOutMap[ this.aChildrenArray[i].getState() ] );
continue;
+ }
this.aChildrenArray[i].removeEffect();
}
};
@@ -6458,7 +6470,9 @@ SequentialTimeContainer.prototype.skipEffect = function( aChildNode )
if( this.isChildNode( aChildNode ) )
{
this.getContext().aActivityQueue.endAll();
+ this.getContext().bIsSkipping = true;
this.getContext().aTimerEventQueue.forceEmpty();
+ this.getContext().bIsSkipping = false;
var aEvent = makeEvent( bind2( aChildNode.deactivate, aChildNode ) );
this.getContext().aTimerEventQueue.addEvent( aEvent );
}
@@ -8589,6 +8603,7 @@ AnimatedElement.prototype.notifyNextEffectStart = function( nEffectIndex )
AnimatedElement.prototype.saveState = function( nAnimationNodeId )
{
+ ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').saveState(' + nAnimationNodeId +')' );
if( !this.aStateSet[ nAnimationNodeId ] )
{
this.aStateSet[ nAnimationNodeId ] = new Object();
@@ -8602,15 +8617,17 @@ AnimatedElement.prototype.saveState = function( nAnimationNodeId )
};
-AnimatedElement.prototype.setTo = function( nAnimationNodeId )
+AnimatedElement.prototype.restoreState = function( nAnimationNodeId )
{
if( !this.aStateSet[ nAnimationNodeId ] )
{
- log( 'AnimatedElement(' + this.getId() + ').setTo: state '
+ log( 'AnimatedElement(' + this.getId() + ').restoreState: state '
+nAnimationNodeId + ' is not valid' );
return false;
}
+ ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').restoreState(' + nAnimationNodeId +')' );
+
var aState = this.aStateSet[ nAnimationNodeId ];
var bRet = this.setToElement( aState.aElement );
if( bRet )
@@ -11196,8 +11213,8 @@ function SlideShow()
this.eDirection = FORWARD;
this.bIsIdle = true;
this.bIsEnabled = true;
- this.bIsSkipping = false;
this.bIsRewinding = false;
+ this.bIsSkipping = false;
this.bNoSlideTransition = false;
}
@@ -11548,6 +11565,7 @@ function SlideShowContext( aTimerEventQueue, aEventMultiplexer, aNextEffectEvent
this.aEventMultiplexer = aEventMultiplexer;
this.aNextEffectEventArray = aNextEffectEventArray;
this.aActivityQueue = aActivityQueue;
+ this.bIsSkipping = false;
}
commit 159a45d06cc3d0e21b2b4e4b470591385db3503a
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Sat Jun 30 22:30:47 2012 +0200
Implemented partial support for rewinding a single shape effect.
Reworked the way saving/restoring the state of an animated shape is implemented.
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
index 0de9bea..c71cad6 100644
--- a/filter/source/svg/presentation_engine.js
+++ b/filter/source/svg/presentation_engine.js
@@ -146,7 +146,7 @@ function getDefaultKeyCodeDictionary()
// slide mode
keyCodeDict[SLIDE_MODE][LEFT_KEY]
- = function() { return dispatchEffects(-1); };
+ = function() { return aSlideShow.rewindEffect(); };
keyCodeDict[SLIDE_MODE][RIGHT_KEY]
= function() { return dispatchEffects(1); };
keyCodeDict[SLIDE_MODE][UP_KEY]
@@ -1433,7 +1433,7 @@ var NAVDBG = new DebugPrinter();
NAVDBG.off();
var ANIMDBG = new DebugPrinter();
-ANIMDBG.on();
+ANIMDBG.off();
var aRegisterEventDebugPrinter = new DebugPrinter();
aRegisterEventDebugPrinter.off();
@@ -3126,6 +3126,9 @@ function bind( aObject, aMethod )
function bind2( aFunction )
{
+ if( !aFunction )
+ log( 'bind2: passed function is not valid.' );
+
var aBoundArgList = arguments;
var aResultFunction = null;
@@ -5272,6 +5275,7 @@ BaseNode.prototype.getParentNode = function()
BaseNode.prototype.init = function()
{
+ this.DBG( this.callInfo( 'init' ) );
if( ! this.checkValidNode() )
return false;
if( this.aActivationEvent )
@@ -5652,7 +5656,6 @@ function AnimationBaseNode( aAnimElem, aParentNode, aNodeContext )
this.bIsContainer = false;
this.aTargetElement = null;
this.aAnimatedElement = null;
- this.nAnimatedElementOriginalState = 0;
this.aActivity = null;
this.nMinFrameCount = undefined;
@@ -5740,7 +5743,7 @@ AnimationBaseNode.prototype.activate_st = function()
{
if( this.aActivity )
{
- this.nAnimatedElementOriginalState = this.getAnimatedElement().getCurrentState();
+ this.saveStateOfAnimatedElement();
this.aActivity.setTargets( this.getAnimatedElement() );
this.getContext().aActivityQueue.addActivity( this.aActivity );
}
@@ -5813,12 +5816,13 @@ AnimationBaseNode.prototype.hasPendingAnimation = function()
AnimationBaseNode.prototype.saveStateOfAnimatedElement = function()
{
- this.getAnimatedElement().saveState();
+ this.getAnimatedElement().saveState( this.getId() );
};
AnimationBaseNode.prototype.removeEffect = function()
{
- this.getAnimatedElement().setTo( this.nAnimatedElementOriginalState );
+ log( 'AnimationBaseNode.removeEffect invoked' );
+ this.getAnimatedElement().setTo( this.getId() );
};
AnimationBaseNode.prototype.getTargetElement = function()
@@ -6268,7 +6272,15 @@ BaseContainerNode.prototype.repeat = function()
BaseContainerNode.prototype.removeEffect = function()
{
- this.forEachChildNode( mem_fn( 'removeEffect' ), FROZEN_NODE | ENDED_NODE );
+ var nChildrenCount = this.aChildrenArray.length;
+ if( nChildrenCount == 0 )
+ return;
+ for( var i = nChildrenCount - 1; i >= 0; --i )
+ {
+ if( ( this.aChildrenArray[i].getState() & FROZEN_NODE | ENDED_NODE ) == 0 )
+ continue;
+ this.aChildrenArray[i].removeEffect();
+ }
};
BaseContainerNode.prototype.saveStateOfAnimatedElement = function()
@@ -6383,7 +6395,10 @@ function SequentialTimeContainer( aAnimElem, aParentNode, aNodeContext )
SequentialTimeContainer.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
this.sClassName = 'SequentialTimeContainer';
+ this.bIsRewinding = false;
this.aCurrentSkipEvent = null;
+ this.aRewindCurrentEffectEvent = null;
+ this.aRewindLastEffectEvent = null;
}
extend( SequentialTimeContainer, BaseContainerNode );
@@ -6412,6 +6427,10 @@ SequentialTimeContainer.prototype.activate_st = function()
SequentialTimeContainer.prototype.notifyDeactivating = function( aNotifier )
{
+ // If we are rewinding we have not to resolve the next child.
+ if( this.bIsRewinding )
+ return;
+
if( this.notifyDeactivatedChild( aNotifier ) )
return;
@@ -6438,6 +6457,7 @@ SequentialTimeContainer.prototype.skipEffect = function( aChildNode )
{
if( this.isChildNode( aChildNode ) )
{
+ this.getContext().aActivityQueue.endAll();
this.getContext().aTimerEventQueue.forceEmpty();
var aEvent = makeEvent( bind2( aChildNode.deactivate, aChildNode ) );
this.getContext().aTimerEventQueue.addEvent( aEvent );
@@ -6448,9 +6468,54 @@ SequentialTimeContainer.prototype.skipEffect = function( aChildNode )
}
};
-SequentialTimeContainer.prototype.rewindEffect = function( aChildNode )
+SequentialTimeContainer.prototype.rewindCurrentEffect = function( aChildNode )
{
- // not implemented
+ if( this.isChildNode( aChildNode ) )
+ {
+ assert( !this.bIsRewinding, 'SequentialTimeContainer.rewindCurrentEffect: is already rewinding.' );
+
+ this.bIsRewinding = true;
+ this.getContext().aTimerEventQueue.forceEmpty();
+ this.getContext().aActivityQueue.clear();
+
+ aChildNode.end();
+ aChildNode.removeEffect();
+ aChildNode.init();
+ this.resolveChild( aChildNode );
+ this.bIsRewinding = false;
+ }
+ else
+ {
+ log( 'SequentialTimeContainer.rewindCurrentEffect: unknown child: ' + aChildNode.getId() );
+ }
+};
+
+SequentialTimeContainer.prototype.rewindLastEffect = function( aChildNode )
+{
+ if( this.isChildNode( aChildNode ) )
+ {
+ assert( !this.bIsRewinding, 'SequentialTimeContainer.rewindLastEffect: is already rewinding.' );
+
+ this.bIsRewinding = true;
+ this.getContext().aTimerEventQueue.forceEmpty();
+ this.getContext().aActivityQueue.clear();
+
+ aChildNode.end();
+ aChildNode.removeEffect();
+ --this.nFinishedChildren;
+ var aPreviousChildNode = this.aChildrenArray[ this.nFinishedChildren ];
+ aPreviousChildNode.removeEffect();
+ aPreviousChildNode.init();
+ // We need to re-initialize it too, because it is in state ENDED now,
+ // and cannot be resolved again later.
+ aChildNode.init();
+ this.resolveChild( aPreviousChildNode );
+ this.bIsRewinding = false;
+ }
+ else
+ {
+ log( 'SequentialTimeContainer.rewindLastEffect: unknown child: ' + aChildNode.getId() );
+ }
};
SequentialTimeContainer.prototype.resolveChild = function( aChildNode )
@@ -6459,13 +6524,23 @@ SequentialTimeContainer.prototype.resolveChild = function( aChildNode )
if( bResolved && this.isMainSequenceRootNode() )
{
- aChildNode.saveStateOfAnimatedElement();
-
if( this.aCurrentSkipEvent )
this.aCurrentSkipEvent.dispose();
- this.aCurrentSkipEvent = makeEvent( bind2( this.skipEffect, this, aChildNode ) );
+ this.aCurrentSkipEvent = makeEvent( bind2( SequentialTimeContainer.prototype.skipEffect, this, aChildNode ) );
this.aContext.aEventMultiplexer.registerSkipEffectEvent( this.aCurrentSkipEvent );
+
+ if( this.aRewindCurrentEffectEvent )
+ this.aRewindCurrentEffectEvent.dispose();
+
+ this.aRewindCurrentEffectEvent = makeEvent( bind2( SequentialTimeContainer.prototype.rewindCurrentEffect, this, aChildNode ) );
+ this.aContext.aEventMultiplexer.registerRewindEffectEvent( this.aRewindCurrentEffectEvent );
+
+ if( this.aRewindLastEffectEvent )
+ this.aRewindLastEffectEvent.dispose();
+
+ this.aRewindLastEffectEvent = makeEvent( bind2( SequentialTimeContainer.prototype.rewindLastEffect, this, aChildNode ) );
+ this.aContext.aEventMultiplexer.registerRewindLastEffectEvent( this.aRewindLastEffectEvent );
}
return bResolved;
};
@@ -8356,7 +8431,7 @@ function AnimatedElement( aElement )
this.aClipPathContent = null;
this.aPreviousElement = null;
- this.aStateArray = new Array();
+ this.aStateSet = new Object();
this.eAdditiveMode = ADDITIVE_MODE_REPLACE;
this.bIsUpdated = true;
@@ -8366,7 +8441,6 @@ function AnimatedElement( aElement )
this.aICTM = document.documentElement.createSVGMatrix();
this.initElement();
- //this.aElementArray[0] = this.aActiveElement.cloneNode( true );
}
AnimatedElement.prototype.initElement = function()
@@ -8377,7 +8451,6 @@ AnimatedElement.prototype.initElement = function()
this.nScaleFactorY = 1.0;
this.setCTM();
- this.nCurrentState = -1;
// add a transform attribute of type matrix
this.aActiveElement.setAttribute( 'transform', makeMatrixString( 1, 0, 0, 1, 0, 0 ) );
};
@@ -8439,11 +8512,6 @@ AnimatedElement.prototype.getId = function()
return this.aActiveElement.getAttribute( 'id' );
};
-AnimatedElement.prototype.getCurrentState = function()
-{
- return this.nCurrentState;
-};
-
AnimatedElement.prototype.isUpdated = function()
{
return this.bIsUpdated;
@@ -8519,46 +8587,34 @@ AnimatedElement.prototype.notifyNextEffectStart = function( nEffectIndex )
// ++this.nCurrentState;
};
-AnimatedElement.prototype.saveState = function()
+AnimatedElement.prototype.saveState = function( nAnimationNodeId )
{
- ++this.nCurrentState;
- if( !this.aStateArray[ this.nCurrentState ] )
+ if( !this.aStateSet[ nAnimationNodeId ] )
{
- this.aStateArray[ this.nCurrentState ] = new Object();
- var aState = this.aStateArray[ this.nCurrentState ];
- aState.aElement = this.aActiveElement.cloneNode( true );
- aState.nCenterX = this.nCenterX;
- aState.nCenterY = this.nCenterY;
- aState.nScaleFactorX = this.nScaleFactorX;
- aState.nScaleFactorY = this.nScaleFactorY;
+ this.aStateSet[ nAnimationNodeId ] = new Object();
}
-};
+ var aState = this.aStateSet[ nAnimationNodeId ];
+ aState.aElement = this.aActiveElement.cloneNode( true );
+ aState.nCenterX = this.nCenterX;
+ aState.nCenterY = this.nCenterY;
+ aState.nScaleFactorX = this.nScaleFactorX;
+ aState.nScaleFactorY = this.nScaleFactorY;
-AnimatedElement.prototype.setToFirst = function()
-{
- this.setTo( 0 );
};
-AnimatedElement.prototype.setToLast = function()
+AnimatedElement.prototype.setTo = function( nAnimationNodeId )
{
- this.setTo( this.aStateArray.length - 1 );
-};
-
-AnimatedElement.prototype.setTo = function( nNewState )
-{
- if( !this.aStateArray[ nNewState ] )
+ if( !this.aStateSet[ nAnimationNodeId ] )
{
log( 'AnimatedElement(' + this.getId() + ').setTo: state '
- + nNewState + ' is not valid' );
+ +nAnimationNodeId + ' is not valid' );
return false;
}
- var aState = this.aStateArray[ nNewState ];
+ var aState = this.aStateSet[ nAnimationNodeId ];
var bRet = this.setToElement( aState.aElement );
if( bRet )
{
- this.nCurrentState = nNewState;
-
this.nCenterX = aState.nCenterX;
this.nCenterY = aState.nCenterY;
this.nScaleFactorX = aState.nScaleFactorX;
@@ -9600,6 +9656,8 @@ function EventMultiplexer( aTimerEventQueue )
this.aTimerEventQueue = aTimerEventQueue;
this.aEventMap = new Object();
this.aSkipEffectEvent = null;
+ this.aRewindEffectEvent = null;
+ this.aRewindLastEffectEvent = null;
}
@@ -9649,6 +9707,34 @@ EventMultiplexer.prototype.notifySkipEffectEvent = function()
}
};
+EventMultiplexer.prototype.registerRewindEffectEvent = function( aEvent )
+{
+ this.aRewindEffectEvent = aEvent;
+};
+
+EventMultiplexer.prototype.notifyRewindEffectEvent = function()
+{
+ if( this.aRewindEffectEvent )
+ {
+ this.aTimerEventQueue.addEvent( this.aRewindEffectEvent );
+ this.aRewindEffectEvent = null;
+ }
+};
+
+EventMultiplexer.prototype.registerRewindLastEffectEvent = function( aEvent )
+{
+ this.aRewindLastEffectEvent = aEvent;
+};
+
+EventMultiplexer.prototype.notifyRewindLastEffectEvent = function()
+{
+ if( this.aRewindLastEffectEvent )
+ {
+ this.aTimerEventQueue.addEvent( this.aRewindLastEffectEvent );
+ this.aRewindLastEffectEvent = null;
+ }
+};
+
EventMultiplexer.DEBUG = aEventMultiplexerDebugPrinter.isEnabled();
EventMultiplexer.prototype.DBG = function( sMethodName, eEventType, aNotifierId, nTime )
@@ -11111,6 +11197,7 @@ function SlideShow()
this.bIsIdle = true;
this.bIsEnabled = true;
this.bIsSkipping = false;
+ this.bIsRewinding = false;
this.bNoSlideTransition = false;
}
@@ -11237,7 +11324,7 @@ SlideShow.prototype.nextEffect = function()
SlideShow.prototype.skipCurrentEffect = function()
{
- if( this.bIsSkipping )
+ if( this.bIsSkipping || this.bIsRewinding )
return;
this.bIsSkipping = true;
@@ -11246,9 +11333,28 @@ SlideShow.prototype.skipCurrentEffect = function()
this.bIsSkipping = false;
};
+SlideShow.prototype.rewindEffect = function()
+{
+ if( this.bIsSkipping || this.bIsRewinding )
+ return true;
+
+ this.bIsRewinding = true;
+ if( this.isRunning() )
+ {
+ this.aEventMultiplexer.notifyRewindEffectEvent();
+ }
+ else
+ {
+ this.aEventMultiplexer.notifyRewindLastEffectEvent();
+ }
+ --this.nCurrentEffect;
+ this.update();
+ this.bIsRewinding = false;
+};
+
SlideShow.prototype.skipEffect = function()
{
- if( this.bIsSkipping )
+ if( this.bIsSkipping || this.bIsRewinding )
return true;
if( this.isRunning() )
@@ -11274,15 +11380,15 @@ SlideShow.prototype.skipEffect = function()
return true;
};
-SlideShow.prototype.previousEffect = function()
-{
- if( this.nCurrentEffect <= 0 )
- return false;
- this.eDirection = BACKWARD;
- this.aNextEffectEventArray.at( this.nCurrentEffect ).fire();
- --this.nCurrentEffect;
- return true;
-};
+//SlideShow.prototype.previousEffect = function()
+//{
+// if( this.nCurrentEffect <= 0 )
+// return false;
+// this.eDirection = BACKWARD;
+// this.aNextEffectEventArray.at( this.nCurrentEffect ).fire();
+// --this.nCurrentEffect;
+// return true;
+//};
SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
{
@@ -11516,12 +11622,12 @@ NextEffectEventArray.prototype.appendEvent = function( aEvent )
{
if( this.aEventArray[i].getId() == aEvent.getId() )
{
- aNextEffectEventArrayDebugPrinter.print( 'NextEffectEventArray.appendEvent: event already present' );
+ aNextEffectEventArrayDebugPrinter.print( 'NextEffectEventArray.appendEvent: event(' + aEvent.getId() + ') already present' );
return false;
}
}
this.aEventArray.push( aEvent );
- aNextEffectEventArrayDebugPrinter.print( 'NextEffectEventArray.appendEvent: event appended' );
+ aNextEffectEventArrayDebugPrinter.print( 'NextEffectEventArray.appendEvent: event(' + aEvent.getId() + ') appended' );
return true;
};
@@ -11542,7 +11648,7 @@ function TimerEventQueue( aTimer )
TimerEventQueue.prototype.addEvent = function( aEvent )
{
- this.DBG( 'TimerEventQueue.addEvent invoked' );
+ this.DBG( 'TimerEventQueue.addEvent event(' + aEvent.getId() + ') appended.' );
if( !aEvent )
{
log( 'TimerEventQueue.addEvent: null event' );
@@ -11748,6 +11854,21 @@ ActivityQueue.prototype.clear = function()
this.aCurrentActivityReinsertSet = new Array();
};
+ActivityQueue.prototype.endAll = function()
+{
+ aActivityQueueDebugPrinter.print( 'ActivityQueue.endAll invoked' );
+ var nSize = this.aCurrentActivityWaitingSet.length;
+ var i;
+ for( i = 0; i < nSize; ++i )
+ this.aCurrentActivityWaitingSet[i].end();
+ this.aCurrentActivityWaitingSet = new Array();
+
+ nSize = this.aCurrentActivityReinsertSet.length;
+ for( i = 0; i < nSize; ++i )
+ this.aCurrentActivityReinsertSet[i].end();
+ this.aCurrentActivityReinsertSet = new Array();
+};
+
ActivityQueue.prototype.getTimer = function()
{
return this.aTimer;
commit 6bfaabf4fe0a1ccf55ae238f690cebd641e6c425
Author: Marco Cecchetti <mrcekets at gmail.com>
Date: Thu Jun 28 23:17:33 2012 +0200
Now a skip effect command cannot be executed if one skip effect is already running.
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list