package events;
interface EventDispatcher {
public var id (default, null) : String;
public var broadcaster : Broadcaster;
}
class Event<T> {
public var type(default,null) : EventType<T>;
public function new( t ) {
type = t;
}
}
class EventType<T> {
public var name(default,null) :String;
public function new( name:String ) {
this.name = name;
}
public function toString() {
return name;
}
}
private class EventRegistration<T> {
var previous : EventRegistration;
var next : EventRegistration;
var handler : Event<T> -> Void;
public var type (default, null) : EventType<T>;
public function new ( type : EventType<T>, handler : Event<T> -> Void ) {
this.dispatcher = dispatcher;
this.type = type;
this.handler = handler;
}
public function dispatch ( event : Event<T> ) : Void {
handler( event );
if( next != null ) {
next.dispatch( event );
}
}
public function remove () : Void {
previous.next = next;
if( next != null ) {
next.previous = previous;
}
}
}
private class EventRegistrationChain<T> extends EventRegistration<T> {
public function new () {
//
}
public function dispatch ( event : Event<T> ) : Void {
if( next != null ) {
next.dispatch( event );
}
}
public function add ( registration : EventRegistration<T> ) : Void {
if( next != null ) {
registration.next = next;
next.previous = registration;
}
next = registration;
}
}
private class Dispatcher<T> {
var list : EventRegistrationChain<T>;
public function new () {
list = new EventRegistrationChain<T>();
}
public function dispatch ( e : Event<T> ) : Void {
list.dispatch( e );
}
public function subscribe ( registration : EventRegistration<T> ) : Void {
list.add( registration );
}
}
class Broadcaster {
var dispatchers : Hash<Dispatcher<Dynamic>>;
public function new () {
dispatchers = new Hash<Dispatcher<Dynamic>>();
}
public function subscribe ( handler : Event<T> -> Void, type : EventType<T> ) : EventRegistration<T> {
var dispatcher = dispatchers.get( type.toString() );
if( dispatcher == null ) {
dispatcher = new Dispatcher<T>();
dispatchers.set( type.toString(), dispatcher );
}
var registration = new EventRegistration<T>( type, handler );
dispatcher.subscribe( registration );
return registration;
}
public function dispatch ( event : Event<Dynamic> ) : Void {
dispatchers.get( event.type.toString() ).dispatch( event );
}
}
class SubscriptionManager {
var subscriptions : Hash<Hash<EventRegistration>>
public function new () {
subscriptions = new Hash<Hash<EventRegistration>>();
}
public function subscribe ( handler : Event<T> -> Void, dispatcher : EventDispatcher, type : EventType<T> ) {
var subscriptionsOfEvent = subscriptions.get( type.toString() );
if( subscriptionsOfEvent == null ) {
subscriptionsOfEvent = new Hash<EventRegistration>();
subscriptions.set( type.toString(), subscriptionsOfEvent );
}
if( !subscriptionsOfEvent.exists( dispatcher.id ) ) {
subscriptionsOfEvent.set( dispatcher.id, dispatcher.broadcaster.subscribe( handler, type ) );
}
}
public function unsubscribe ( type : EventType, ?dispatcher : EventDispatcher ) : Void {
var subscriptionsOfEvent = subscriptions.get( type.toString() );
if( dispatcher != null ) {
subscriptionsOfEvent.get( dispatcher.id ).remove();
subscriptionsOfEvent.remove( dispatcher.id );
} else {
for( var registration in subscriptionsOfEvent ) {
registration.remove();
}
}
}
public function disable ( type : EventType ) : Void {
var subscriptionsOfEvent = subscriptions.get( type.toString() );
for( var registration in subscriptionsOfEvent ) {
registration.disable();
}
}
public function enable ( type : EventType ) : Void {
var subscriptionsOfEvent = subscriptions.get( type.toString() );
for( var registration in subscriptionsOfEvent ) {
registration.enable();
}
}
}