package events; interface EventDispatcher { public var id (default, null) : String; public var broadcaster : Broadcaster; } class Event { public var type(default,null) : EventType; public function new( t ) { type = t; } } class EventType { public var name(default,null) :String; public function new( name:String ) { this.name = name; } public function toString() { return name; } } private class EventRegistration { var previous : EventRegistration; var next : EventRegistration; var handler : Event -> Void; public var type (default, null) : EventType; public function new ( type : EventType, handler : Event -> Void ) { this.dispatcher = dispatcher; this.type = type; this.handler = handler; } public function dispatch ( event : Event ) : 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 extends EventRegistration { public function new () { // } public function dispatch ( event : Event ) : Void { if( next != null ) { next.dispatch( event ); } } public function add ( registration : EventRegistration ) : Void { if( next != null ) { registration.next = next; next.previous = registration; } next = registration; } } private class Dispatcher { var list : EventRegistrationChain; public function new () { list = new EventRegistrationChain(); } public function dispatch ( e : Event ) : Void { list.dispatch( e ); } public function subscribe ( registration : EventRegistration ) : Void { list.add( registration ); } } class Broadcaster { var dispatchers : Hash>; public function new () { dispatchers = new Hash>(); } public function subscribe ( handler : Event -> Void, type : EventType ) : EventRegistration { var dispatcher = dispatchers.get( type.toString() ); if( dispatcher == null ) { dispatcher = new Dispatcher(); dispatchers.set( type.toString(), dispatcher ); } var registration = new EventRegistration( type, handler ); dispatcher.subscribe( registration ); return registration; } public function dispatch ( event : Event ) : Void { dispatchers.get( event.type.toString() ).dispatch( event ); } } class SubscriptionManager { var subscriptions : Hash> public function new () { subscriptions = new Hash>(); } public function subscribe ( handler : Event -> Void, dispatcher : EventDispatcher, type : EventType ) { var subscriptionsOfEvent = subscriptions.get( type.toString() ); if( subscriptionsOfEvent == null ) { subscriptionsOfEvent = new Hash(); 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(); } } }