git » sdk » main » tree

[main] / borogove / EventEmitter.hx

package borogove;

#if cpp
import HaxeCBridge;
#end

enum EventResult {
	EventHandled;
	EventUnhandled;
	EventStop;
	EventValue(result:Dynamic);
}

typedef EventCallback = (Dynamic)->EventResult;

typedef EventHandlerToken = Int;

@:expose
#if cpp
@:build(HaxeCBridge.expose())
@:build(HaxeSwiftBridge.expose())
#end
class EventEmitter {
	private var nextEventHandlerToken = 0;
	private var eventHandlers:Map<String,Map<EventHandlerToken, EventCallback>> = [];

	private function new() { }

	@:allow(borogove)
	private function on(eventName:String, callback:EventCallback):EventHandlerToken {
		var handlers = eventHandlers.get(eventName);
		if(handlers == null) {
			handlers = [];
			eventHandlers.set(eventName, handlers);
		}
		final token = nextEventHandlerToken++;
		handlers[token] = callback;
		return token;
	}

	@:allow(borogove)
	private function once(eventName:String, callback:EventCallback):Void {
		var token = null;
		token = this.on(eventName, (e) -> {
			if (token == null) throw "Somehow token was not ready";
			this.removeEventListener(token);
			return callback(e);
		});
	}

	@:allow(borogove)
	private function trigger(eventName:String, eventData:Dynamic):EventResult {
		final handlers = eventHandlers.get(eventName);
		if (handlers == null) return EventUnhandled;

		trace("firing event: "+eventName);
		var handled = false;
		for (handler in handlers) {
			var ret = handler(eventData);
			switch(ret) {
				case EventHandled: handled = true;
				case EventUnhandled: continue;
				case EventStop | EventValue(_): return ret;
			}
		}
		return handled ? EventHandled : EventUnhandled;
	}

	/**
		Remove an event listener of any type, no matter how it was added
		or what event it is for.

		@param token the token that was returned when the listener was added
	**/
	public function removeEventListener(token:EventHandlerToken) {
		for (handlers in eventHandlers) {
			handlers.remove(token);
		}
	}
}