Skip to content

Commit

Permalink
migrate LocalEventEmitterMapExtension extension to repo and use Event…
Browse files Browse the repository at this point in the history
…Emitter implementation from Phaser
  • Loading branch information
tiagoschenkel committed Mar 1, 2020
1 parent 5f80015 commit d7c5923
Show file tree
Hide file tree
Showing 10 changed files with 1,240 additions and 17 deletions.
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ export { SceneRegistryEvent } from "./robotlegs/bender/extensions/viewManager/im
export { SceneManagerExtension } from "./robotlegs/bender/extensions/viewManager/SceneManagerExtension";
export { SceneManagerObserverExtension } from "./robotlegs/bender/extensions/viewManager/SceneManagerObserverExtension";

/**
* LocalEventEmitterMap
*/
export { IEventEmitterMap } from "./robotlegs/bender/extensions/localEventEmitterMap/api/IEventEmitterMap";
export { EventEmitterMap } from "./robotlegs/bender/extensions/localEventEmitterMap/impl/EventEmitterMap";
export { EventEmitterMapConfig } from "./robotlegs/bender/extensions/localEventEmitterMap/impl/EventEmitterMapConfig";
export { LocalEventEmitterMapExtension } from "./robotlegs/bender/extensions/localEventEmitterMap/LocalEventEmitterMapExtension";

/**
* Bundles
*/
Expand Down
3 changes: 1 addition & 2 deletions src/robotlegs/bender/bundles/phaser/PhaserBundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

import { IBundle, IContext, ILogger, instanceOfType } from "@robotlegsjs/core";

import { LocalEventEmitterMapExtension } from "@robotlegsjs/eventemitter3";

import { IContextSceneManager } from "../../extensions/contextSceneManager/api/IContextSceneManager";
import { ContextSceneManager } from "../../extensions/contextSceneManager/impl/ContextSceneManager";
import { ContextSceneManagerListenerConfig } from "../../extensions/contextSceneManager/impl/ContextSceneManagerListenerConfig";
Expand All @@ -19,6 +17,7 @@ import { ViewMediatorMapExtension } from "../../extensions/mediatorMap/ViewMedia

import { SceneManagerExtension } from "../../extensions/viewManager/SceneManagerExtension";
import { SceneManagerObserverExtension } from "../../extensions/viewManager/SceneManagerObserverExtension";
import { LocalEventEmitterMapExtension } from "../../extensions/localEventEmitterMap/LocalEventEmitterMapExtension";

/**
* For that Classic Robotlegs flavour
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// ------------------------------------------------------------------------------
// Copyright (c) 2017-present, RobotlegsJS. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
// ------------------------------------------------------------------------------

import { IContext, IExtension } from "@robotlegsjs/core";

import { IEventEmitterMap } from "./api/IEventEmitterMap";
import { EventEmitterMap } from "./impl/EventEmitterMap";

/**
* An Event Map keeps track of listeners and provides the ability
* to unregister all listeners with a single method call.
*/
export class LocalEventEmitterMapExtension implements IExtension {
/*============================================================================*/
/* Public Functions */
/*============================================================================*/

/**
* @inheritDoc
*/
public extend(context: IContext): void {
context.injector.bind(IEventEmitterMap).to(EventEmitterMap);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// ------------------------------------------------------------------------------
// Copyright (c) 2017-present, RobotlegsJS. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
// ------------------------------------------------------------------------------

import { IEventMap } from "@robotlegsjs/core";

/**
* The Event Emitter Map keeps track of listeners and provides the ability
* to unregister all Phaser.Events.EventEmitter listeners with a single method call.
*/
export const IEventEmitterMap = Symbol("IEventEmitterMap");
export interface IEventEmitterMap extends IEventMap {
/**
* The same as calling <code>on</code> or <code>addListener</code> directly on the <code>Phaser.Events.EventEmitter</code>,
* but keeps a list of listeners for easy (usually automatic) removal.
*
* @param emitter The <code>Phaser.Events.EventEmitter</code> to listen to
* @param event The <code>event</code> type to listen for
* @param listener The <code>event</code> handler
* @param context the listener function's "this"
*/
on(emitter: Phaser.Events.EventEmitter, event: string | symbol, listener: Function, context?: any): void;

/**
* The same as calling <code>once</code> directly on the <code>Phaser.Events.EventEmitter</code>,
* but keeps a list of listeners for easy (usually automatic) removal.
*
* @param emitter The <code>Phaser.Events.EventEmitter</code> to listen to
* @param event The <code>event</code> type to listen for
* @param listener The <code>event</code> handler
* @param context the listener function's "this"
*/
once(emitter: Phaser.Events.EventEmitter, event: string | symbol, listener: Function, context?: any): void;

/**
* The same as calling <code>off</code> or <code>removeListener</code> directly on the <code>Phaser.Events.EventEmitter</code>,
* but updates our local list of listeners.
*
* @param emitter The <code>Phaser.Events.EventEmitter</code> to listen to
* @param event The <code>event</code> type to listen for
* @param listener The <code>event</code> handler
* @param context the listener function's "this"
*/
off(emitter: Phaser.Events.EventEmitter, event: string | symbol, listener?: Function, context?: any): void;

/**
* Removes all listeners registered through <code>on</code> or <code>once</code>
*/
unmapEventEmitterListeners(): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
// ------------------------------------------------------------------------------
// Copyright (c) 2017-present, RobotlegsJS. All Rights Reserved.
//
// NOTICE: You are permitted to use, modify, and distribute this file
// in accordance with the terms of the license agreement accompanying it.
// ------------------------------------------------------------------------------

import { injectable, EventMap } from "@robotlegsjs/core";

import { IEventEmitterMap } from "../api/IEventEmitterMap";
import { EventEmitterMapConfig } from "./EventEmitterMapConfig";

/**
* @private
*/
@injectable()
export class EventEmitterMap extends EventMap implements IEventEmitterMap {
/*============================================================================*/
/* Protected Properties */
/*============================================================================*/

protected _eventEmitterListeners: EventEmitterMapConfig[] = [];
protected _suspendedEventEmitterListeners: EventEmitterMapConfig[] = [];

protected get _currentEventEmitterListeners(): EventEmitterMapConfig[] {
return this._suspended ? this._suspendedEventEmitterListeners : this._eventEmitterListeners;
}

/*============================================================================*/
/* Public Functions */
/*============================================================================*/

/**
* @inheritDoc
*/
public on(emitter: Phaser.Events.EventEmitter, event: string | symbol, listener: Function, context?: any): void {
this._registerEventEmitterListener(emitter, event, listener, context);
}

/**
* @inheritDoc
*/
public once(emitter: Phaser.Events.EventEmitter, event: string | symbol, listener: Function, context?: any): void {
this._registerEventEmitterListener(emitter, event, listener, context, true);
}

/**
* @inheritDoc
*/
public off(emitter: Phaser.Events.EventEmitter, event: string | symbol, listener: Function, context?: any): void {
this._unregisterEventEmitterListener(emitter, event, listener, context);
}

/**
* @inheritDoc
*/
public unmapEventEmitterListeners(): void {
let eventConfig: EventEmitterMapConfig;

while (this._currentEventEmitterListeners.length) {
eventConfig = this._currentEventEmitterListeners[this._currentEventEmitterListeners.length - 1];
this._unregisterEventEmitterListener(eventConfig.emitter, eventConfig.event, eventConfig.listener, eventConfig.context);
}
}

/**
* @inheritDoc
*/
public unmapAllListeners(): void {
super.unmapAllListeners();

this.unmapEventEmitterListeners();
}

/**
* @inheritDoc
*/
public suspend(): void {
if (this._suspended) {
return;
}

// Handle Phaser.Events.EventEmitter's
let emitter: Phaser.Events.EventEmitter;

this._eventEmitterListeners.forEach((eventConfig: EventEmitterMapConfig) => {
emitter = eventConfig.emitter;
if (eventConfig.once) {
emitter.off(eventConfig.event, eventConfig.calback, eventConfig.context, eventConfig.once);
} else {
emitter.off(eventConfig.event, eventConfig.listener, eventConfig.context, eventConfig.once);
}
this._suspendedEventEmitterListeners.push(eventConfig);
});

this._eventEmitterListeners = [];

super.suspend();
}

/**
* @inheritDoc
*/
public resume(): void {
if (!this._suspended) {
return;
}

// Handle Phaser.Events.EventEmitter's
let emitter: Phaser.Events.EventEmitter;

this._suspendedEventEmitterListeners.forEach((eventConfig: EventEmitterMapConfig) => {
emitter = eventConfig.emitter;
if (eventConfig.once) {
emitter.once(eventConfig.event, eventConfig.calback, eventConfig.context);
} else {
emitter.on(eventConfig.event, eventConfig.listener, eventConfig.context);
}
this._eventEmitterListeners.push(eventConfig);
});

this._suspendedEventEmitterListeners = [];

super.resume();
}

/*============================================================================*/
/* Protected Functions */
/*============================================================================*/

protected _registerEventEmitterListener(
emitter: Phaser.Events.EventEmitter,
event: string | symbol,
listener: Function,
context?: any,
once?: boolean
): void {
let config: EventEmitterMapConfig;

let i: number = this._currentEventEmitterListeners.length;
while (i--) {
config = this._currentEventEmitterListeners[i];
if (config.equalTo(emitter, event, listener, context)) {
return;
}
}

if (once) {
config = new EventEmitterMapConfig(emitter, event, listener, context, once);
config.calback = this._onceCallback(config);
} else {
config = new EventEmitterMapConfig(emitter, event, listener, context);
}

this._currentEventEmitterListeners.push(config);

if (!this._suspended) {
if (once) {
emitter.once(event, config.calback, context);
} else {
emitter.on(event, listener, context);
}
}
}

protected _onceCallback(eventConfig: EventEmitterMapConfig): Function {
return (...args: any[]): void => {
let i: number = this._currentEventEmitterListeners.length;

while (i--) {
let config: EventEmitterMapConfig = this._currentEventEmitterListeners[i];
if (config.equalTo(eventConfig.emitter, eventConfig.event, eventConfig.listener, eventConfig.context)) {
this._currentEventEmitterListeners.splice(i, 1);
eventConfig.listener.apply(eventConfig.context, args);
return;
}
}
};
}

protected _unregisterEventEmitterListener(
emitter: Phaser.Events.EventEmitter,
event: string | symbol,
listener: Function,
context?: any
): void {
let i: number = this._currentEventEmitterListeners.length;
while (i--) {
let config: EventEmitterMapConfig = this._currentEventEmitterListeners[i];
if (config.equalTo(emitter, event, listener, context)) {
if (!this._suspended) {
if (config.once) {
emitter.off(event, config.calback, config.context, config.once);
} else {
emitter.off(event, config.listener, config.context, config.once);
}
}
this._currentEventEmitterListeners.splice(i, 1);
return;
}
}
}
}
Loading

0 comments on commit d7c5923

Please sign in to comment.