138 lines
4.0 KiB
TypeScript
138 lines
4.0 KiB
TypeScript
//import { MOUNT_CLASS_TO } from "../config/debug";
|
|
import type { ArgumentTypes, SuperReturnType } from "../types";
|
|
|
|
// class EventSystem {
|
|
// wm: WeakMap<any, Record<any, Set<any>>> = new WeakMap();
|
|
|
|
// add(target: any, event: any, listener: any) {
|
|
// let listeners = this.wm.get(target);
|
|
// if (listeners === undefined) {
|
|
// listeners = {};
|
|
// }
|
|
// let listenersForEvent = listeners[event];
|
|
// if (listenersForEvent === undefined) {
|
|
// listenersForEvent = new Set();
|
|
// }
|
|
// listenersForEvent.add(listener);
|
|
// listeners[event] = listenersForEvent;
|
|
// //target.addEventListener(event, listener);
|
|
// this.wm.set(target, listeners);
|
|
// };
|
|
|
|
// remove(target: any, event: any, listener: any) {
|
|
// let listeners = this.wm.get(target);
|
|
// if (!listeners) return;
|
|
// let listenersForEvent = listeners[event];
|
|
// if (!listenersForEvent) return;
|
|
// listenersForEvent.delete(listener);
|
|
// };
|
|
|
|
// /* fire(target, event) {
|
|
// let listeners = this.wm.get(target);
|
|
// if (!listeners) return;
|
|
// let listenersForEvent = listeners[event];
|
|
// if (!listenersForEvent) return;
|
|
// for (let handler of handlers) {
|
|
// setTimeout(handler, 0, event, target); // we use a setTimeout here because we want event triggering to be asynchronous.
|
|
// }
|
|
// }; */
|
|
// }
|
|
|
|
// console.log = () => {};
|
|
|
|
// const e = new EventSystem();
|
|
// MOUNT_CLASS_TO && (MOUNT_CLASS_TO.e = e);
|
|
|
|
/**
|
|
* Better not to remove listeners during setting
|
|
* Should add listener callback only once
|
|
*/
|
|
export default class EventListenerBase<Listeners extends {[name: string]: Function}> {
|
|
protected listeners: Partial<{
|
|
[k in keyof Listeners]: Array<{callback: Listeners[k], once?: boolean}>
|
|
}>;
|
|
protected listenerResults: Partial<{
|
|
[k in keyof Listeners]: ArgumentTypes<Listeners[k]>
|
|
}>;
|
|
|
|
private reuseResults: boolean;
|
|
|
|
constructor(reuseResults?: boolean) {
|
|
this._constructor(reuseResults);
|
|
}
|
|
|
|
public _constructor(reuseResults = false): any {
|
|
this.reuseResults = reuseResults;
|
|
this.listeners = {};
|
|
this.listenerResults = {};
|
|
}
|
|
|
|
public addListener(name: keyof Listeners, callback: Listeners[typeof name], once?: boolean) {
|
|
if(this.listenerResults.hasOwnProperty(name)) {
|
|
callback(...this.listenerResults[name]);
|
|
|
|
if(once) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
(this.listeners[name] ?? (this.listeners[name] = [])).push({callback, once});
|
|
//e.add(this, name, {callback, once});
|
|
}
|
|
|
|
public removeListener(name: keyof Listeners, callback: Listeners[typeof name]) {
|
|
if(this.listeners[name]) {
|
|
this.listeners[name].findAndSplice(l => l.callback === callback);
|
|
}
|
|
//e.remove(this, name, callback);
|
|
}
|
|
|
|
// * must be protected, but who cares
|
|
public setListenerResult(name: keyof Listeners, ...args: ArgumentTypes<Listeners[typeof name]>) {
|
|
if(this.reuseResults) {
|
|
this.listenerResults[name] = args;
|
|
}
|
|
|
|
const arr: Array<SuperReturnType<Listeners[typeof name]>> = [];
|
|
|
|
/* let a = e.wm.get(this)[name];
|
|
if(!a) return arr;
|
|
const listeners = [...a]; */
|
|
const listeners = this.listeners[name];
|
|
if(listeners) {
|
|
// ! this one will guarantee execution even if delete another listener during setting
|
|
const left = listeners.slice();
|
|
left.forEach((listener: any) => {
|
|
const index = listeners.findIndex((l: any) => l.callback === listener.callback);
|
|
if(index === -1) {
|
|
return;
|
|
}
|
|
|
|
arr.push(listener.callback(...args));
|
|
|
|
if(listener.once) {
|
|
this.removeListener(name, listener.callback);
|
|
}
|
|
});
|
|
|
|
/* for(let i = 0, length = listeners.length; i < length; ++i) {
|
|
const listener = listeners[i];
|
|
arr.push(listener.callback(...args));
|
|
|
|
if(listener.once) {
|
|
listeners.splice(i, 1);
|
|
--i;
|
|
--length;
|
|
}
|
|
} */
|
|
}
|
|
|
|
return arr;
|
|
}
|
|
|
|
public cleanup() {
|
|
this.listeners = {};
|
|
this.listenerResults = {};
|
|
}
|
|
}
|