Event Dispatcher

One easy way for your script to gain event dispatching capabilities is to inherit the “EventDispatcher” script.
For example, this is your button behaviour:

Show code

— Button behaviour script
property ancestor
property myType
property myID

on beginSprite( me )
ancestor = script( "EventDispatcher" ).rawNew()
callAncestor( #new, me, me )
myType = #pushButton
sprite( me.spritenum ).cursor = 280
me.dispatchEvent( #buttonReady, [ #id:myID ] )
end beginSprite

on mouseUp( me )
me.dispatchEvent( #buttonClick, [#type:myType, #id:myID] )
end mouseUp

on getPropertyDescriptionList( me )
pdl = propList()
pdl.addProp( #myID, [ #format:#symbol, #default: symbol( "button"&_player.currentSpritenum ), #comment:"WidgetID:" ] )
return pdl
end getPropertyDescriptionList


And this is your ColourPicker behaviour:
Show code

— ColourPicker behaviour script
property ancestor
property myID
property myType
property mySprite
property myColor

on beginSprite( me )
ancestor = script( "EventDispatcher" ).rawNew()
callAncestor( #new, me, me )
mySprite = sprite( me.spritenum )
myColor = me.randomColor()
mySprite.color = myColor
myType = #colorPicker
sprite( me.spritenum ).cursor = 280
me.dispatchEvent( #colorReady, [#id:myID, #color:myColor] )
end beginSprite

on mouseUp( me )
myColor = me.randomColor()
mySprite.color = myColor
me.dispatchEvent( #colorChange,[ #type:myType, #id:myID, #color:myColor ] )
end mouseUp

on randomColor( me )
r = random( 64, 225 )
g = random( 64, 190 )
b = random( 64, 128 )
return( color( r, g, b ) )
end randomColor

on getPropertyDescriptionList( me )
pdl = propList()
pdl.addProp( #myID, [ #format:#symbol, #default: symbol( "color"&_player.currentSpritenum ), #comment:"WidgetID:" ] )
return pdl
end getPropertyDescriptionList


Now, you can combine all of the application “logic” in one place:
Show code

— Main Frame Script
property display

on beginSprite( me )
_movie.puppetTempo( 90 )
display = sprite( "DISPLAY" ).member
display.text = EMPTY
end beginSprite

on exitFrame( me )
_movie.go( _movie.frame )
end exitFrame

on buttonReady( me, event )
event.sender.addEventListener( #buttonClick, #display, me )
end buttonReady

on colorReady( me, event )
event.sender.addEventListener( #colorChange, #display, me )
end colorReady

— Application "logic"
on display( me, event )
args = event.args
case( args.type ) of
#pushButton :
case( args.id ) of
#button1: msg = "FIRST BUTTON WAS CLICKED"
#button2: msg = "SECOND BUTTON WAS CLICKED"
#button3: msg = "THIRD BUTTON WAS CLICKED"
end case
display.color = color( 0,0,0 )
display.text = string( msg )
#colorPicker:
_title = "The colour in _ was changed to" && args.color
case( args.id ) of
#color1: cp = "COLOURPICKER1"
#color2: cp = "COLOURPICKER2"
end case
x = offset( "_", _title )
put cp into char x of _title
x = offset( "color(", _title )
display.text = string( _title )
display.char[ x..(_title.length) ].color = args.color
end case
end display


The “EventDispatcher” script is listed below:

Show code

— EventDispatcher parent script
— Author: Vladin M. Mitov
— October, 2010
— Last update – May, 2012
— https://www.ed-multimedia.com

— addEventListener( SymbolEventName, SymbolCallbackMethod, ObjectListener )
— removeEventListener( ObjectListener, SymbolEventName, SymbolCallbackMethod )
— hasEventListeners( SymbolEventName ) : #Boolean
— removeAllEventListeners()
— dispatchEvent( SymbolEventName, [ args ] )
— stopEvent()
— events( me ) : #List with registered events

————————————————-
— FIELDS
————————————————-
on ___________________________PROPERTIES
end

property successor
property _listeners
property _temp
————————————————-
— CONSTRUCTOR
————————————————-
on ___________________________CONSTRUCTOR
end
on new( me, s )
if( voidP( s ) ) then
successor = me
else
successor = s
end if
_listeners = propList()
_temp = propList()
return me
end new

————————————————-
— PUBLIC METHODS
————————————————-
on ___________________________PUBLIC_METHODS
end

on dispose( me )
successor = VOID
if ( _listeners.ilk = #propList ) then
repeat with i in _listeners
i.deleteAll()
end repeat
end if
end dispose

on addEventListener( me, aeventName, acallbackMethod, alistener )
case ( alistener.ilk ) of
#instance, #sprite, #_movie, #window:
if ( _listeners.findPos (aeventName ) = 0 ) then
_listeners.addprop( aeventName, [ : ] )
end if
if ( voidP( _listeners[ aeventName ].findPos( acallbackMethod ) ) ) then
_listeners[ aeventName ].addProp( acallbackMethod, list() )
end if
if ( _listeners[ aeventName ][ acallbackMethod ].getPos( alistener ) = 0 ) then
_listeners[ aeventName ][ acallbackMethod ].append( alistener )
end if
otherwise:
me._exception( "Invalid listener type:" && ilk( alistener ) & RETURN & \
"A listener type must be"& RETURN & "#instance, #sprite, #_movie or #window." )
abort
end case
end addEventListener

on removeEventListener( me, alistener, aEventName, acallbackMethod )
ecnt = count( _listeners )
repeat with e = ecnt down to 1
if( aEventName = _listeners.getPropAt( e ) ) then
event = _listeners[ e ]
ccnt = event.count
repeat with c = ccnt down to 1
callback = event.getPropAt( c )
if( acallbackMethod = callback ) then
objects = event[ c ]
ocnt = count( objects )
repeat with l = ocnt down to 1
if( alistener = objects[ l ].listener ) then
objects.deleteAt( l )
end if
end repeat
if( count( objects ) = 0 ) then
event.deleteProp( callback )
end if
end if
end repeat
if( count( event ) = 0 ) then
_listeners.deleteProp( aEventName )
end if
end if
end repeat
end removeListener

on hasEventListeners( me, aEventName )
return not voidP( _listeners.findPos( aEventName ) )
end hasEventListeners

on removeAllEventListeners( me )
cnt = count( _listeners )
repeat with i = cnt down to 1
_listeners[ i ].deleteAll()
end repeat
_listeners.deleteAll()
end removeAllEventListeners

on dispatchEvent( me, aeventName, args )
if voidP( _listeners.findPos( aeventName ) ) then
sendAllSprites( aeventName, [ #sender:successor, #args:args ] )
return
end if
_temp = _listeners[ aeventName ].duplicate()
cnt = count( _temp )
repeat with i = cnt down to 1
callback = _temp.getPropAt( i )
receivers = _temp[ i ]
call( callback, receivers, [ #type:aeventName, #sender:successor, #args:args ] )
end repeat
end dispatchEvent

on stopEvent( me )
receivers = _temp[ 1 ]
cnt = count( receivers )
receivers.deleteAll()
end stopEvent

on events( me )
t = list()
repeat with i = 1 to count( _listeners )
t.append( _listeners.getPropAt( i ) )
end repeat
return t
end events

on interface( me )
msg = EMPTY
put "addEventListener( SymbolEventName, SymbolCallbackMethod, ObjectListener, { parameterList } )" & RETURN after msg
put "removeEventListener( ObjectListener, SymbolEventName, SymbolCallbackMethod )" & RETURN after msg
put "hasEventListeners( SymbolEventName )" & RETURN after msg
put "removeAllEventListeners()" & RETURN after msg
put "dispatchEvent( SymbolEventName, ObjectSender, { args } )" & RETURN after msg
put "stopEvent()" & RETURN after msg
put "events( me ) – Returns a list with registered events." after msg
return msg
end interface

————————————————-
— PRIVATE METHODS
————————————————-
on ___________________________PRIVATE_METHODS
end

on _exception( me, msg )
_player.alert( msg )
_movie.halt() — place a breakpoint here
end _exception

Event Dispatcher demo
Event Dispatcher (7885 downloads)
 
Comments

Added / updated the following methods:

hasEventListeners( SymbolEventName )
dispatchEvent( SymbolEventName, PropListOfArguments )

Added stopEvent() method.

Example:

on eventHandler( event )
if( condition = true ) then
event.sender.stopEvent()
end if
end eventHandler

Leave a Reply