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
/*
SignalHub:
Created on Sat 15th Sep, 2012
by Lee Grey
SignalHub 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 SignalHub instances by key, or use the default instance
//default:
var signalHub = SignalHub.getHub();
//string key:
var signalHub = SignalHub.getHub( 'specificHub' );
var signalHub = SignalHub.getHub( 'ui' );
var signalHub = SignalHub.getHub( 'soundFX' );
//use class as key:
var signalHub = SignalHub.getHub( MyClass );
//use instace as key:
var signalHub = SignalHub.getHub( someInstance );
//optional Signal definition for type safety:
signalHub.defineSignal( 'someEvent', Number, Number );
//Cache references to signals for performance-critical situations
var someEventSignal:Signal = signalHub.defineSignal( 'someEvent', Number, Number );
var someEventSignal:Signal = signalHub.getSignal( 'someEvent' );
//add listeners:
signalHub.add( 'someEvent', onSomeEventHandler );
signalHub.addOnce( 'someEvent', onSomeEventHandler );
//add listener to a particular instance:
SignalHub.getHub( instance ).add( 'someEvent', onSomeEventHandler );
//Cache references to signals for performance-critical situations:
var someEventSignal:Signal = signalHub.defineSignal( 'someEvent', Number, Number );
var someEventSignal:Signal = signalHub.getSignal( 'someEvent' );
//dispatch through SignalHub:
signalHub.dispatch( 'someEvent', x, y );
// dispatch the cached signal:
someEventSignal.dispatch( x, y );
// dispatch for a specific instance:
SignalHub.getHub( 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 signalHub:SignalHub = SignalHub.getHub( XYZ );
public const aSignal:Signal = signalHub.defineSignal( 'someEvent', Number, Number );
public const bSignal:Signal = signalHub.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...
SignalHub.getHub( XYZ ).add( 'someEvent', handler );
Note that any instance of XYZSignalGroup created will point to the same
signals, no matter where or when it is created.
// Alternatively, a group with static members:
class XYZSignals {
//use the class XYZSignals as a key:
private static const signalHub:SignalHub = SignalHub.getHub( XYZSignalGroup );
public static const aSignal:Signal = signalHub.defineSignal( 'someEvent', Number, Number );
public static const bSignal:Signal = signalHub.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 SignalHub {
private static var instances:Dictionary = new Dictionary();
private var signals:Dictionary = new Dictionary();
public function SignalHub()
{
}
//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( 'SignalHub::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( 'SignalHub::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 getHub( key:* = 'defaultInstance' ):SignalHub
{
var signalHub:SignalHub = instances[ key ];
if( !signalHub ) signalHub = instances[ key ] = new SignalHub();
return signalHub;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment