Starting Settings modules + implemented basic events for ECMAScript <=> Qt compat.
This commit is contained in:
parent
9663c33563
commit
af2950c3d2
5 changed files with 276 additions and 5 deletions
96
common/src/events.mjs
Normal file
96
common/src/events.mjs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/**
|
||||||
|
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
|
||||||
|
* Copyright (C) 2021-2024 Ad5001
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We do not inherit the DOM's Event, because not only the DOM part is unnecessary,
|
||||||
|
* but also because it does not exist within Qt environments.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export class BaseEvent {
|
||||||
|
/**
|
||||||
|
* @property {string} name - Name of the event.
|
||||||
|
*/
|
||||||
|
constructor(name) {
|
||||||
|
this.name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all classes which can emit events.
|
||||||
|
*/
|
||||||
|
export class BaseEventEmitter {
|
||||||
|
static emits = []
|
||||||
|
|
||||||
|
/** @type {Record<string, function[]>} */
|
||||||
|
#listeners = {}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
for(const eventType of this.constructor.emits) {
|
||||||
|
this.#listeners[eventType] = new Set()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a listener to an event that can be emitted by this object.
|
||||||
|
*
|
||||||
|
* @param {string} eventType - Name of the event to listen to. Throws an error if this object does not emit this kind of event.
|
||||||
|
* @param {function(BaseEvent)} eventListener - The function to be called back when the event is emitted.
|
||||||
|
*/
|
||||||
|
addEventListener(eventType, eventListener) {
|
||||||
|
if(!this.emits.includes(eventType)) {
|
||||||
|
const className = this.constructor.name
|
||||||
|
const eventTypes = this.constructor.emits.join(", ")
|
||||||
|
throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`)
|
||||||
|
}
|
||||||
|
if(!this.#listeners[eventType].has(eventListener))
|
||||||
|
this.#listeners[eventType].add(eventListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remvoes a listener from an event that can be emitted by this object.
|
||||||
|
*
|
||||||
|
* @param {string} eventType - Name of the event that was listened to. Throws an error if this object does not emit this kind of event.
|
||||||
|
* @param {function(BaseEvent)} eventListener - The function previously registered as a listener.
|
||||||
|
* @returns {boolean} True if the listener was removed, false if it was not found.
|
||||||
|
*/
|
||||||
|
removeEventListener(eventType, eventListener) {
|
||||||
|
if(!this.emits.includes(eventType)) {
|
||||||
|
const className = this.constructor.name
|
||||||
|
const eventTypes = this.constructor.emits.join(", ")
|
||||||
|
throw new Error(`Cannot listen to unknown event ${eventType} in class ${className}. ${className} only emits: ${eventTypes}`)
|
||||||
|
}
|
||||||
|
return this.#listeners[eventType].delete(eventListener)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits an event to all of its listeners.
|
||||||
|
*
|
||||||
|
* @param {BaseEvent} e
|
||||||
|
*/
|
||||||
|
emit(e) {
|
||||||
|
if(!(e instanceof BaseEvent))
|
||||||
|
throw new Error("Cannot emit non event object.")
|
||||||
|
if(!this.emits.includes(e.name))
|
||||||
|
throw new Error(`Cannot emit event '${e.name}' from class ${this.constructor.name}. ${this.constructor.name} can only emits: ${this.constructor.emits.join(", ")}.`)
|
||||||
|
for(const listener of this.#listeners[e.name])
|
||||||
|
listener(e)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
/**
|
/*!
|
||||||
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
|
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
|
||||||
* Copyright (C) 2021-2024 Ad5001
|
* Copyright (C) 2021-2024 Ad5001
|
||||||
*
|
*
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Interface } from "./interface.mjs"
|
import { Interface } from "./interface.mjs"
|
||||||
|
import { BaseEventEmitter } from "../events.mjs"
|
||||||
|
|
||||||
// Define Modules interface before they are imported.
|
// Define Modules interface before they are imported.
|
||||||
globalThis.Modules = globalThis.Modules || {}
|
globalThis.Modules = globalThis.Modules || {}
|
||||||
|
@ -24,7 +25,7 @@ globalThis.Modules = globalThis.Modules || {}
|
||||||
/**
|
/**
|
||||||
* Base class for global APIs in runtime.
|
* Base class for global APIs in runtime.
|
||||||
*/
|
*/
|
||||||
export class Module {
|
export class Module extends BaseEventEmitter {
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
#name
|
#name
|
||||||
/** @type {Object.<string, (Interface|string|number|boolean)>} */
|
/** @type {Object.<string, (Interface|string|number|boolean)>} */
|
||||||
|
@ -36,6 +37,7 @@ export class Module {
|
||||||
* @param {Object.<string, (Interface|string|number|boolean)>} initializationParameters - List of parameters for the initialize function.
|
* @param {Object.<string, (Interface|string|number|boolean)>} initializationParameters - List of parameters for the initialize function.
|
||||||
*/
|
*/
|
||||||
constructor(name, initializationParameters = {}) {
|
constructor(name, initializationParameters = {}) {
|
||||||
|
super()
|
||||||
console.log(`Loading module ${name}...`)
|
console.log(`Loading module ${name}...`)
|
||||||
this.#name = name
|
this.#name = name
|
||||||
this.#initializationParameters = initializationParameters
|
this.#initializationParameters = initializationParameters
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*!
|
/**
|
||||||
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
|
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
|
||||||
*
|
*
|
||||||
* @author Ad5001 <mail@ad5001.eu>
|
* @author Ad5001 <mail@ad5001.eu>
|
||||||
|
|
173
common/src/module/settings.mjs
Normal file
173
common/src/module/settings.mjs
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
/**
|
||||||
|
* LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions.
|
||||||
|
* Copyright (C) 2021-2024 Ad5001
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Module } from "./common.mjs"
|
||||||
|
import { BaseEvent } from "../events.mjs"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base event for when a setting was changed.
|
||||||
|
*/
|
||||||
|
class ChangedEvent extends BaseEvent {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} property - Name of the property that was chagned
|
||||||
|
* @param {string|number|boolean} oldValue - Old value of the property
|
||||||
|
* @param {string|number|boolean} newValue - Current (new) value of the property
|
||||||
|
* @param {boolean} byUser - True if the user is at the source of the change in the setting.
|
||||||
|
*/
|
||||||
|
constructor(property, oldValue, newValue, byUser) {
|
||||||
|
super("changed")
|
||||||
|
|
||||||
|
this.property = property
|
||||||
|
this.oldValue = oldValue
|
||||||
|
this.newValue = newValue
|
||||||
|
this.byUser = byUser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module for graph settings.
|
||||||
|
*/
|
||||||
|
class SettingsAPI extends Module {
|
||||||
|
static emits = ["changed"]
|
||||||
|
|
||||||
|
#properties = new Map([
|
||||||
|
['xzoom', 100],
|
||||||
|
['yzoom', 10],
|
||||||
|
['xmin', .5],
|
||||||
|
['ymax', 25],
|
||||||
|
['xaxisstep', "4"],
|
||||||
|
['yaxisstep', "4"],
|
||||||
|
['xlabel', ""],
|
||||||
|
['ylabel', ""],
|
||||||
|
['linewidth', 1],
|
||||||
|
['textsize', 18],
|
||||||
|
['logscalex', true],
|
||||||
|
['showxgrad', true],
|
||||||
|
['showygrad', true],
|
||||||
|
])
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super("Settings", {
|
||||||
|
helper: HelperInterface
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize({ helper }) {
|
||||||
|
super.initialize({ helper })
|
||||||
|
// Initialize default values.
|
||||||
|
for(const key of this.#properties.keys()) {
|
||||||
|
switch(typeof this.#properties.get(key)) {
|
||||||
|
case 'boolean':
|
||||||
|
this.set(key, helper.getSettingBool(key), false)
|
||||||
|
break
|
||||||
|
case 'number':
|
||||||
|
this.set(key, helper.getSettingInt(key), false)
|
||||||
|
break
|
||||||
|
case 'string':
|
||||||
|
this.set(key, helper.getSetting(key), false)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a setting to a given value
|
||||||
|
*
|
||||||
|
* @param {boolean} byUser - Set to true if the user is at the origin of this change.
|
||||||
|
*/
|
||||||
|
set(property, value, byUser) {
|
||||||
|
if(!this.#properties.has(property))
|
||||||
|
throw new Error(`Property ${property} is not a setting.`)
|
||||||
|
const oldValue = this.#properties.get(property)
|
||||||
|
const propType = typeof oldValue
|
||||||
|
if(propType !== typeof value)
|
||||||
|
throw new Error(`Value of ${property} must be a ${propType}.`)
|
||||||
|
this.#properties.set(property, value)
|
||||||
|
this.emit(new ChangedEvent(property, oldValue, value, byUser === true))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zoom on the x axis of the diagram.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
get xzoom() { return this.#properties.get("xzoom"); }
|
||||||
|
/**
|
||||||
|
* Zoom on the y axis of the diagram.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
get yzoom() { return this.#properties.get("yzoom"); }
|
||||||
|
/**
|
||||||
|
* Minimum x of the diagram.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
get xmin() { return this.#properties.get("xmin"); }
|
||||||
|
/**
|
||||||
|
* Maximum y of the diagram.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
get ymax() { return this.#properties.get("ymax"); }
|
||||||
|
/**
|
||||||
|
* Step of the x axis graduation (expression).
|
||||||
|
* @note Only available in non-logarithmic mode.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
get xaxisstep() { return this.#properties.get("xaxisstep"); }
|
||||||
|
/**
|
||||||
|
* Step of the y axis graduation (expression).
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
get yaxisstep() { return this.#properties.get("yaxisstep"); }
|
||||||
|
/**
|
||||||
|
* Label used on the x axis.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
get xlabel() { return this.#properties.get("xlabel"); }
|
||||||
|
/**
|
||||||
|
* Label used on the y axis.
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
get ylabel() { return this.#properties.get("ylabel"); }
|
||||||
|
/**
|
||||||
|
* Width of lines that will be drawn into the canvas.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
get linewidth() { return this.#properties.get("linewidth"); }
|
||||||
|
/**
|
||||||
|
* Font size of the text that will be drawn into the canvas.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
get textsize() { return this.#properties.get("textsize"); }
|
||||||
|
/**
|
||||||
|
* true if the canvas should be in logarithmic mode, false otherwise.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get logscalex() { return this.#properties.get("logscalex"); }
|
||||||
|
/**
|
||||||
|
* true if the x graduation should be shown, false otherwise.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get showxgrad() { return this.#properties.get("showxgrad"); }
|
||||||
|
/**
|
||||||
|
* true if the y graduation should be shown, false otherwise.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get showygrad() { return this.#properties.get("showygrad"); }
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue