Skip to content

Instantly share code, notes, and snippets.

@leegrey
Created September 15, 2012 07:48
Show Gist options
  • Save leegrey/3726860 to your computer and use it in GitHub Desktop.
Save leegrey/3726860 to your computer and use it in GitHub Desktop.
SignalHub.as is a Signal manager for AS3
/*
SignalNode:
Created on Sat 15th Sep, 2012
by Lee Grey
SignalNode solves the problem of object-creation order by using lazy initialisation - whoever
makes the first request for a Signal with a given key will bring about it's creation.
Listeners can be added to a Signal even before the dispatching class
has optionally defined the type-signature of the Signal
Usage:
// create SignalNode instances by key, or use the default instance
//default:
var signalNode = SignalNode.getNode();
//string key:
var signalNode = SignalNode.getNode( 'specificNode' );
var signalNode = SignalNode.getNode( 'ui' );
var signalNode = SignalNode.getNode( 'soundFX' );
//use class as key:
var signalNode = SignalNode.getNode( MyClass );
//use instace as key:
var signalNode = SignalNode.getNode( someInstance );
//optional Signal definition for type safety:
signalNode.defineSignal( 'someEvent', Number, Number );
//Cache references to signals for performance-critical situations
var someEventSignal:Signal = signalNode.defineSignal( 'someEvent', Number, Number );
var someEventSignal:Signal = signalNode.getSignal( 'someEvent' );
//add listeners:
signalNode.add( 'someEvent', onSomeEventHandler );
signalNode.addOnce( 'someEvent', onSomeEventHandler );
//add listener to a particular instance:
SignalNode.getNode( instance ).add( 'someEvent', onSomeEventHandler );
//Cache references to signals for performance-critical situations:
var someEventSignal:Signal = signalNode.defineSignal( 'someEvent', Number, Number );
var someEventSignal:Signal = signalNode.getSignal( 'someEvent' );
//dispatch through SignalNode:
signalNode.dispatch( 'someEvent', x, y );
// dispatch the cached signal:
someEventSignal.dispatch( x, y );
// dispatch for a specific instance:
SignalNode.getNode( this ).dispatch( x, y );
Static signal groups:
Using statc groups ensures that signals are created and
available to the application immediately
//for class XYZ, create a static instance of a group of signals:
class XYZSignalGroup {
//use the class XYZ as a key:
private const signalNode:SignalNode = SignalNode.getNode( XYZ );
public const aSignal:Signal = signalNode.defineSignal( 'someEvent', Number, Number );
public const bSignal:Signal = signalNode.defineSignal( 'someOtherEvent', Number, Number );
}
// within XYZ class:
public static const signals:XYZSignalGroup = new XYZSignalGroup();
// now access signals like this:
XYZ.signals.aSignal.add( 'someEvent', handler );
// or...
SignalNode.getNode( XYZ ).add( 'someEvent', handler );
// Alternatively, a group with static members:
class XYZSignals {
//use the class XYZSignals as a key:
private static const signalNode:SignalNode = SignalNode.getNode( XYZSignalGroup );
public static const aSignal:Signal = signalNode.defineSignal( 'someEvent', Number, Number );
public static const bSignal:Signal = signalNode.defineSignal( 'someOtherEvent', Number, Number );
}
//access like this:
XYZSignals.aSignal.add( 'someEvent', handler );
*/
package com.lgrey.signal {
import flash.utils.Dictionary;
import org.osflash.signals.Signal;
public class SignalNode {
private static var instances:Dictionary = new Dictionary();
private var signals:Dictionary = new Dictionary();
public function SignalNode()
{
}
/*public static function defineSignal( key:*, ...types ):Signal
{
}*/
//use defineSignal to create type safe signals
public function defineSignal( key:*, ...types ):Signal
{
var signal:Signal = signals[ key ];
//warn if overwriting
if( signal ) { // assert( signals[ key ], 'warning....' )
trace( 'SignalNode::defineSignal() - Warning, signal already existed for this key.'
+ ' Overwriting valueClasses.' );
} else {
signal = signals[ key ] = new Signal();
}
//set / update valueClasses
signal.valueClasses = types;
return signal
}
public function add( key:*, closure:Function ):Signal
{
var signal:Signal = signals[ key ];
if( !signal ) signal = signals[ key ] = new Signal();
signal.add( closure );
return signal;
}
public function addOnce( key:*, closure:Function ):Signal
{
var signal:Signal = signals[ key ];
if( !signal ) signal = signals[ key ] = new Signal();
signal.addOnce( closure );
return signal;
}
public function remove( key:*, closure:Function ):Signal
{
var signal:Signal = signals[ key ];
if( signal ) signal.remove( closure );
return signal;
}
// using apply() results in a significant performance hit
// in performance-critical situations, cache the Signal reference
// returned by defineSignal() and getSignal()
public function dispatch( key:*, ...args ):Signal
{
var signal:Signal = signals[ key ];
if( signal ) signal.dispatch.apply( null, args );
else trace( 'SignalNode::dispatch() - Warning, no signal with key:', key );
return signal;
}
public function getSignal( key:* ):Signal
{
var signal:Signal = signals[ key ];
if( !signal ) signal = signals[ key ] = new Signal();
return signal;
}
public static function getNode( key:* = 'defaultInstance' ):SignalNode
{
var signalNode:SignalNode = instances[ key ];
if( !signalNode ) signalNode = instances[ key ] = new SignalNode();
return signalNode;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment