@geogirafe/lib-geoportal
Version:
GeoGirafe is a flexible application to build online geoportals.
116 lines (115 loc) • 5.75 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
import GirafeSingleton from '../../base/GirafeSingleton.js';
import { gGEventDependencies } from './userinteractionevent.js';
/**
* Manages user interactions (mouse and keyboard events) by registering and unregistering listeners with the state.
* The manager provides proper handling of user interaction events by reassigning events to the active tool,
* providing logic for exclusive listeners, and reverting back to defaults when tools are closed.
*/
class UserInteractionManager extends GirafeSingleton {
state = this.context.stateManager.state;
get listenersInState() {
return this.state.userInteractionListeners;
}
/**
* Registers a listener for the specified interaction event. If the listener is exclusive,
* it removes pre-existing exclusive listeners for the same event before registering the new one.
* Ensures that duplicate listeners are not registered.
*
* @param {GgUserInteractionEvent} eventName - The event name to register the listener for.
* @param {boolean} isExclusive - Indicates whether the listener is exclusive to the event.
* Exclusive listeners override other listeners for the same event.
* @param {string} toolName - The name of the tool registering the listener.
* @return {boolean} Returns true if the listener was successfully registered, false if the listener
* was already registered.
*/
registerListener(eventName, isExclusive, toolName) {
if (this.isListenerRegistered(eventName, toolName)) {
// Prevent registering if the listener already exists
return false;
}
if (isExclusive) {
// Remove any pre-existing exclusive listener for the same event (last-one-wins strategy)
this.getExclusiveListenersForEvent(eventName, toolName).forEach((l) => this.unregisterListener(l.eventName, l.toolName));
}
this.listenersInState.push({
eventName: eventName,
isExclusive: isExclusive,
toolName: toolName
});
return true;
}
/**
* Unregisters a listener for a specific interaction event and tool by removing it from the state.
*
* @param {GgUserInteractionEvent} eventName - The name of the interaction event to unregister.
* @param {string} toolName - The name of the tool associated with the event listener to be unregistered.
* @return {void}
*/
unregisterListener(eventName, toolName) {
const index = this.listenersInState.findIndex((l) => l.eventName === eventName && l.toolName === toolName);
if (index > -1) {
this.state.userInteractionListeners.splice(index, 1);
}
}
/**
* Unregisters all listeners associated with a specific tool.
*
* @param {string} toolName - The name of the tool for which all event listeners should be unregistered.
* @return {void}
*/
unregisterAllListenersOfTool(toolName) {
this.listenersInState
.filter((l) => l.toolName === toolName)
.forEach((l) => this.unregisterListener(l.eventName, l.toolName));
}
/**
* Determines whether a listener associated with a specific event and tool can execute.
*
* @param {GgUserInteractionEvent} eventName - The name of the interaction event.
* @param {string} toolName - The name of the tool associated with the event.
* @return {boolean} Returns true if the listener can execute; otherwise, returns false.
*/
canListenerExecute(eventName, toolName) {
if (!this.isListenerRegistered(eventName, toolName)) {
return false;
}
// Prevent if there is an exclusive listener that is not the current tool
if (this.getExclusiveListenersForEvent(eventName, toolName).length > 0) {
return false;
}
// Else, allow execution
return true;
}
/**
* Determines whether a given tool has already registered the event in the state.
*
* @param {GgUserInteractionEvent} eventName - The name of the event to be checked.
* @param {string} toolName - The name of the tool that wants to register an event.
* @return {boolean} Returns true if the GgInteractionListener is already registered.
*/
isListenerRegistered(eventName, toolName) {
return this.listenersInState.find((l) => l.eventName === eventName && l.toolName === toolName) !== undefined;
}
getDependentEvents(eventName) {
return [...(gGEventDependencies[eventName] ?? []), eventName];
}
/**
* Checks whether the specified event is dependent on another event by checking the gGEventDependencies list.
*/
isEventDependentOn(eventName, eventNameToTest) {
return this.getDependentEvents(eventName).includes(eventNameToTest);
}
/**
* Retrieves the exclusive listeners for a specific event, omitting the specified toolName. To request all
* exclusive listeners of that event, omit the toolName parameter.
*
* @param {GgUserInteractionEvent} eventName - The name of the interaction event to filter listeners by.
* @param {string} toolName - The name of the tool to exclude listeners associated with (optional).
* @return {GgUserInteractionListener[]} An array of exclusive listeners matching the specified event and tool exclusion criteria.
*/
getExclusiveListenersForEvent(eventName, toolName) {
return this.listenersInState.filter((l) => this.isEventDependentOn(l.eventName, eventName) && l.isExclusive && l.toolName !== (toolName ?? undefined));
}
}
export default UserInteractionManager;