diff --git a/dist/ueblueprint.js b/dist/ueblueprint.js index 30a6ec9..c3b53c0 100755 --- a/dist/ueblueprint.js +++ b/dist/ueblueprint.js @@ -157,22 +157,32 @@ const html = String.raw; /** * @typedef {import("../element/IElement").default} IElement */ + +/** + * @template {IElement} T + */ class ITemplate { /** - * @param {IElement} entity + * @param {T} entity */ render(entity) { return "" } /** - * @param {IElement} element + * @param {T} element */ - apply(element) { + setup(element) { // TODO replace with the safer element.setHTML(...) when it will be availableBreack element.innerHTML = this.render(element); } + + /** + * @param {T} element + */ + cleanup(element) { + } } // @ts-check @@ -513,8 +523,6 @@ class FastSelectionModel { */ class IElement extends HTMLElement { - static tagName = "" - /** @type {Blueprint} */ #blueprint get blueprint() { @@ -562,15 +570,18 @@ class IElement extends HTMLElement { connectedCallback() { this.#blueprint = this.closest("ueb-blueprint"); - this.template.apply(this); + this.template.setup(this); this.inputObjects = this.createInputObjects(); } disconnectedCallback() { this.inputObjects.forEach(v => v.unlistenDOMElement()); + this.template.cleanup(this); } - /** @param {IElement} element */ + /** + * @param {IElement} element + */ isSameGraph(element) { return this.#blueprint && this.#blueprint == element?.blueprint } @@ -595,14 +606,15 @@ class IElement extends HTMLElement { /** * @typedef {import("../element/SelectorElement").default} SelectorElement */ + class SelectorTemplate extends ITemplate { /** * Applies the style to the element. * @param {SelectorElement} selector Selector element */ - apply(selector) { - super.apply(selector); + setup(selector) { + super.setup(selector); this.applyFinishSelecting(selector); } @@ -645,16 +657,13 @@ class SelectorTemplate extends ITemplate { */ class SelectorElement extends IElement { - static tagName = "ueb-selector" - constructor() { super({}, new SelectorTemplate()); this.selectionModel = null; } /** - * Create a selection rectangle starting from the specified position - * @param {Number[]} initialPosition - Selection rectangle initial position (relative to the .ueb-grid element) + * @param {Number[]} initialPosition */ startSelecting(initialPosition) { this.template.applyStartSelecting(this, initialPosition); @@ -662,8 +671,7 @@ class SelectorElement extends IElement { } /** - * Move selection rectagle to the specified final position. The initial position was specified by startSelecting() - * @param {Number[]} finalPosition - Selection rectangle final position (relative to the .ueb-grid element) + * @param {Number[]} finalPosition */ doSelecting(finalPosition) { this.template.applyDoSelecting(this, finalPosition); @@ -685,6 +693,7 @@ customElements.define("ueb-selector", SelectorElement); * @typedef {import("../element/PinElement").default} PinElement * @typedef {import("../entity/PinReferenceEntity").default} PinReferenceEntity */ + class BlueprintTemplate extends ITemplate { /** @@ -743,8 +752,8 @@ class BlueprintTemplate extends ITemplate { * Applies the style to the element. * @param {Blueprint} blueprint The blueprint element */ - apply(blueprint) { - super.apply(blueprint); + setup(blueprint) { + super.setup(blueprint); blueprint.classList.add("ueb", `ueb-zoom-${blueprint.zoom}`); Object.entries({ "--ueb-font-size": sanitizeText(Configuration.fontSize), @@ -2273,6 +2282,7 @@ class KeyboardSelectAll extends IKeyboardShortcut { * @typedef {import("../element/LinkElement").default} LinkElement * @typedef {import("../element/LinkMessageElement").default} LinkMessageElement */ + class LinkTemplate extends ITemplate { /** @@ -2340,8 +2350,8 @@ class LinkTemplate extends ITemplate { /** * @param {LinkElement} link */ - apply(link) { - super.apply(link); + setup(link) { + super.setup(link); if (link.linkMessageElement) { link.appendChild(link.linkMessageElement); } @@ -2456,8 +2466,6 @@ class LinkTemplate extends ITemplate { */ class LinkElement extends IElement { - static tagName = "ueb-link" - /** @type {PinElement} */ #source get sourcePin() { @@ -3059,6 +3067,7 @@ class ISelectableDraggableElement extends IElement { * @typedef {import("../element/NodeElement").default} NodeElement * @typedef {import("../element/PinElement").default} PinElement */ + class PinTemplate extends ITemplate { hasInput() { @@ -3106,8 +3115,8 @@ class PinTemplate extends ITemplate { /** * @param {PinElement} pin */ - apply(pin) { - super.apply(pin); + setup(pin) { + super.setup(pin); pin.classList.add( "ueb-node-" + (pin.isInput() ? "input" : pin.isOutput() ? "output" : "hidden"), "ueb-pin-" + sanitizeText(pin.getType()) @@ -3147,6 +3156,7 @@ class PinTemplate extends ITemplate { /** * @typedef {import("../element/PinElement").default} PinElement */ + class ExecPinTemplate extends PinTemplate { /** @@ -3166,6 +3176,7 @@ class ExecPinTemplate extends PinTemplate { /** * @typedef {import("../element/LinkMessageElement").default} LinkMessageElement */ + class LinkMessageTemplate extends ITemplate { /** @@ -3182,8 +3193,8 @@ class LinkMessageTemplate extends ITemplate { * Applies the style to the element. * @param {LinkMessageElement} linkMessage */ - apply(linkMessage) { - super.apply(linkMessage); + setup(linkMessage) { + super.setup(linkMessage); const linkMessageSetup = _ => /** @type {HTMLElement} */(linkMessage.querySelector(".ueb-link-message")).innerText = linkMessage.message( linkMessage.linkElement.sourcePin, @@ -3212,7 +3223,6 @@ class LinkMessageTemplate extends ITemplate { */ class LinkMessageElement extends IElement { - static tagName = "ueb-link-message" static convertType = _ => new LinkMessageElement( "ueb-icon-conver-type", /** @type {LinkRetrieval} */ @@ -3375,6 +3385,7 @@ class MouseCreateLink extends IMouseClickDrag { /** * @typedef {import("../element/PinElement").default} PinElement */ + class StringPinTemplate extends PinTemplate { hasInput() { @@ -3397,6 +3408,32 @@ class StringPinTemplate extends PinTemplate { ` } + + /** + * @param {PinElement} pin + */ + setup(pin) { + super.setup(pin); + const input = pin.querySelector(".ueb-pin-input-content"); + this.onFocusHandler = () => { + pin.blueprint.dispatchEditTextEvent(true); + }; + this.onFocusOutHandler = () => { + pin.blueprint.dispatchEditTextEvent(false); + document.getSelection().removeAllRanges(); // Deselect text inside the input + }; + input.addEventListener("onfocus", this.onFocusHandler); + input.addEventListener("onfocusout", this.onFocusOutHandler); + } + + /** + * @param {PinElement} pin + */ + cleanup(pin) { + super.cleanup(pin); + pin.blueprint.removeEventListener("onfocus", this.onFocusHandler); + pin.blueprint.removeEventListener("onfocusout", this.onFocusOutHandler); + } } // @ts-check @@ -3413,8 +3450,6 @@ class StringPinTemplate extends PinTemplate { */ class PinElement extends IElement { - static tagName = "ueb-pin" - static #typeTemplateMap = { "exec": ExecPinTemplate, "string": StringPinTemplate, @@ -3568,6 +3603,7 @@ customElements.define("ueb-pin", PinElement); /** * @typedef {import("../element/ISelectableDraggableElement").default} ISelectableDraggableElement */ + class SelectableDraggableTemplate extends ITemplate { /** @@ -3597,6 +3633,7 @@ class SelectableDraggableTemplate extends ITemplate { /** * @typedef {import("../element/NodeElement").default} NodeElement */ + class NodeTemplate extends SelectableDraggableTemplate { /** @@ -3632,8 +3669,8 @@ class NodeTemplate extends SelectableDraggableTemplate { * Applies the style to the element. * @param {NodeElement} node Element of the graph */ - apply(node) { - super.apply(node); + setup(node) { + super.setup(node); const nodeName = node.entity.getFullName(); node.dataset.name = sanitizeText(nodeName); if (node.selected) { @@ -3680,8 +3717,6 @@ class NodeTemplate extends SelectableDraggableTemplate { */ class NodeElement extends ISelectableDraggableElement { - static tagName = "ueb-node" - /** * @param {ObjectEntity} entity */ @@ -3898,7 +3933,6 @@ class Unfocus extends IContext { */ class Blueprint extends IElement { - static tagName = "ueb-blueprint" /** @type {Number[]} */ #additional get additional() { diff --git a/js/Blueprint.js b/js/Blueprint.js index fe38d5e..9a1a8c2 100755 --- a/js/Blueprint.js +++ b/js/Blueprint.js @@ -29,7 +29,6 @@ import Zoom from "./input/mouse/Zoom" */ export default class Blueprint extends IElement { - static tagName = "ueb-blueprint" /** @type {Number[]} */ #additional get additional() { diff --git a/js/element/IElement.js b/js/element/IElement.js index e6a3896..37602c8 100644 --- a/js/element/IElement.js +++ b/js/element/IElement.js @@ -13,8 +13,6 @@ */ export default class IElement extends HTMLElement { - static tagName = "" - /** @type {Blueprint} */ #blueprint get blueprint() { @@ -62,15 +60,18 @@ export default class IElement extends HTMLElement { connectedCallback() { this.#blueprint = this.closest("ueb-blueprint") - this.template.apply(this) + this.template.setup(this) this.inputObjects = this.createInputObjects() } disconnectedCallback() { this.inputObjects.forEach(v => v.unlistenDOMElement()) + this.template.cleanup(this) } - /** @param {IElement} element */ + /** + * @param {IElement} element + */ isSameGraph(element) { return this.#blueprint && this.#blueprint == element?.blueprint } diff --git a/js/element/LinkElement.js b/js/element/LinkElement.js index 381b13e..a0aa187 100644 --- a/js/element/LinkElement.js +++ b/js/element/LinkElement.js @@ -15,8 +15,6 @@ import LinkTemplate from "../template/LinkTemplate" */ export default class LinkElement extends IElement { - static tagName = "ueb-link" - /** @type {PinElement} */ #source get sourcePin() { diff --git a/js/element/LinkMessageElement.js b/js/element/LinkMessageElement.js index 9ac2e45..897860d 100644 --- a/js/element/LinkMessageElement.js +++ b/js/element/LinkMessageElement.js @@ -14,7 +14,6 @@ import LinkMessageTemplate from "../template/LinkMessageTemplate" */ export default class LinkMessageElement extends IElement { - static tagName = "ueb-link-message" static convertType = _ => new LinkMessageElement( "ueb-icon-conver-type", /** @type {LinkRetrieval} */ diff --git a/js/element/NodeElement.js b/js/element/NodeElement.js index 69c44e0..d3318be 100644 --- a/js/element/NodeElement.js +++ b/js/element/NodeElement.js @@ -13,8 +13,6 @@ import PinReferenceEntity from "../entity/PinReferenceEntity" */ export default class NodeElement extends ISelectableDraggableElement { - static tagName = "ueb-node" - /** * @param {ObjectEntity} entity */ diff --git a/js/element/PinElement.js b/js/element/PinElement.js index 566d516..bb3a604 100644 --- a/js/element/PinElement.js +++ b/js/element/PinElement.js @@ -19,8 +19,6 @@ import StringPinTemplate from "../template/StringPinTemplate" */ export default class PinElement extends IElement { - static tagName = "ueb-pin" - static #typeTemplateMap = { "exec": ExecPinTemplate, "string": StringPinTemplate, diff --git a/js/element/SelectorElement.js b/js/element/SelectorElement.js index a41383d..0613228 100644 --- a/js/element/SelectorElement.js +++ b/js/element/SelectorElement.js @@ -9,16 +9,13 @@ import SelectorTemplate from "../template/SelectorTemplate" */ export default class SelectorElement extends IElement { - static tagName = "ueb-selector" - constructor() { super({}, new SelectorTemplate()) this.selectionModel = null } /** - * Create a selection rectangle starting from the specified position - * @param {Number[]} initialPosition - Selection rectangle initial position (relative to the .ueb-grid element) + * @param {Number[]} initialPosition */ startSelecting(initialPosition) { this.template.applyStartSelecting(this, initialPosition) @@ -26,8 +23,7 @@ export default class SelectorElement extends IElement { } /** - * Move selection rectagle to the specified final position. The initial position was specified by startSelecting() - * @param {Number[]} finalPosition - Selection rectangle final position (relative to the .ueb-grid element) + * @param {Number[]} finalPosition */ doSelecting(finalPosition) { this.template.applyDoSelecting(this, finalPosition) diff --git a/js/selection/SimpleSelectionModel.js b/js/selection/SimpleSelectionModel.js index ea438a3..4ffa984 100755 --- a/js/selection/SimpleSelectionModel.js +++ b/js/selection/SimpleSelectionModel.js @@ -9,11 +9,11 @@ export default class SimpleSelectionModel { * secondaryInf: number, * secondarySup: number * }} BoundariesInfo - * @typedef {numeric} Rectangle + * @typedef {Number} Rectangle * @param {number[]} initialPosition Coordinates of the starting point of selection [primaryAxisValue, secondaryAxisValue]. * @param {Rectangle[]} rectangles Rectangles that can be selected by this object. * @param {(rect: Rectangle) => BoundariesInfo} boundariesFunc A function that, given a rectangle, it provides the boundaries of such rectangle. - * @param {(rect: Rectangle, selected: bool) => void} selectToggleFunction A function that selects or deselects individual rectangles. + * @param {(rect: Rectangle, selected: Boolean) => void} selectToggleFunction A function that selects or deselects individual rectangles. */ constructor(initialPosition, rectangles, boundariesFunc, selectToggleFunction) { this.initialPosition = initialPosition diff --git a/js/template/BlueprintTemplate.js b/js/template/BlueprintTemplate.js index b3a5a54..aafd4f6 100755 --- a/js/template/BlueprintTemplate.js +++ b/js/template/BlueprintTemplate.js @@ -11,6 +11,7 @@ import SelectorElement from "../element/SelectorElement" * @typedef {import("../element/PinElement").default} PinElement * @typedef {import("../entity/PinReferenceEntity").default} PinReferenceEntity */ + export default class BlueprintTemplate extends ITemplate { /** @@ -69,8 +70,8 @@ export default class BlueprintTemplate extends ITemplate { * Applies the style to the element. * @param {Blueprint} blueprint The blueprint element */ - apply(blueprint) { - super.apply(blueprint) + setup(blueprint) { + super.setup(blueprint) blueprint.classList.add("ueb", `ueb-zoom-${blueprint.zoom}`) Object.entries({ "--ueb-font-size": sanitizeText(Configuration.fontSize), diff --git a/js/template/ExecPinTemplate.js b/js/template/ExecPinTemplate.js index bf4a65c..9d3eb9e 100644 --- a/js/template/ExecPinTemplate.js +++ b/js/template/ExecPinTemplate.js @@ -6,6 +6,7 @@ import PinTemplate from "./PinTemplate" /** * @typedef {import("../element/PinElement").default} PinElement */ + export default class ExecPinTemplate extends PinTemplate { /** diff --git a/js/template/ITemplate.js b/js/template/ITemplate.js index 8c37131..6803666 100644 --- a/js/template/ITemplate.js +++ b/js/template/ITemplate.js @@ -3,20 +3,30 @@ /** * @typedef {import("../element/IElement").default} IElement */ + +/** + * @template {IElement} T + */ export default class ITemplate { /** - * @param {IElement} entity + * @param {T} entity */ render(entity) { return "" } /** - * @param {IElement} element + * @param {T} element */ - apply(element) { + setup(element) { // TODO replace with the safer element.setHTML(...) when it will be availableBreack element.innerHTML = this.render(element) } + + /** + * @param {T} element + */ + cleanup(element) { + } } diff --git a/js/template/LinkMessageTemplate.js b/js/template/LinkMessageTemplate.js index 7f4244b..cec5336 100644 --- a/js/template/LinkMessageTemplate.js +++ b/js/template/LinkMessageTemplate.js @@ -2,12 +2,12 @@ import html from "./html" import ITemplate from "./ITemplate" -import LinkElement from "../element/LinkElement" import sanitizeText from "./sanitizeText" /** * @typedef {import("../element/LinkMessageElement").default} LinkMessageElement */ + export default class LinkMessageTemplate extends ITemplate { /** @@ -24,8 +24,8 @@ export default class LinkMessageTemplate extends ITemplate { * Applies the style to the element. * @param {LinkMessageElement} linkMessage */ - apply(linkMessage) { - const a = super.apply(linkMessage) + setup(linkMessage) { + const a = super.setup(linkMessage) const linkMessageSetup = _ => /** @type {HTMLElement} */(linkMessage.querySelector(".ueb-link-message")).innerText = linkMessage.message( linkMessage.linkElement.sourcePin, diff --git a/js/template/LinkTemplate.js b/js/template/LinkTemplate.js index 6e5a09d..747b971 100755 --- a/js/template/LinkTemplate.js +++ b/js/template/LinkTemplate.js @@ -9,6 +9,7 @@ import sanitizeText from "./sanitizeText" * @typedef {import("../element/LinkElement").default} LinkElement * @typedef {import("../element/LinkMessageElement").default} LinkMessageElement */ + export default class LinkTemplate extends ITemplate { /** @@ -76,8 +77,8 @@ export default class LinkTemplate extends ITemplate { /** * @param {LinkElement} link */ - apply(link) { - super.apply(link) + setup(link) { + super.setup(link) if (link.linkMessageElement) { link.appendChild(link.linkMessageElement) } diff --git a/js/template/NodeTemplate.js b/js/template/NodeTemplate.js index 06e5eee..a3e514d 100755 --- a/js/template/NodeTemplate.js +++ b/js/template/NodeTemplate.js @@ -8,6 +8,7 @@ import SelectableDraggableTemplate from "./SelectableDraggableTemplate" /** * @typedef {import("../element/NodeElement").default} NodeElement */ + export default class NodeTemplate extends SelectableDraggableTemplate { /** @@ -43,8 +44,8 @@ export default class NodeTemplate extends SelectableDraggableTemplate { * Applies the style to the element. * @param {NodeElement} node Element of the graph */ - apply(node) { - super.apply(node) + setup(node) { + super.setup(node) const nodeName = node.entity.getFullName() node.dataset.name = sanitizeText(nodeName) if (node.selected) { diff --git a/js/template/PinTemplate.js b/js/template/PinTemplate.js index 1c5bdd4..0675b7a 100755 --- a/js/template/PinTemplate.js +++ b/js/template/PinTemplate.js @@ -9,6 +9,7 @@ import Utility from "../Utility" * @typedef {import("../element/NodeElement").default} NodeElement * @typedef {import("../element/PinElement").default} PinElement */ + export default class PinTemplate extends ITemplate { hasInput() { @@ -56,8 +57,8 @@ export default class PinTemplate extends ITemplate { /** * @param {PinElement} pin */ - apply(pin) { - super.apply(pin) + setup(pin) { + super.setup(pin) pin.classList.add( "ueb-node-" + (pin.isInput() ? "input" : pin.isOutput() ? "output" : "hidden"), "ueb-pin-" + sanitizeText(pin.getType()) diff --git a/js/template/SelectableDraggableTemplate.js b/js/template/SelectableDraggableTemplate.js index bdb66d8..d668b81 100755 --- a/js/template/SelectableDraggableTemplate.js +++ b/js/template/SelectableDraggableTemplate.js @@ -6,6 +6,7 @@ import sanitizeText from "./sanitizeText" /** * @typedef {import("../element/ISelectableDraggableElement").default} ISelectableDraggableElement */ + export default class SelectableDraggableTemplate extends ITemplate { /** diff --git a/js/template/SelectorTemplate.js b/js/template/SelectorTemplate.js index b415b8c..3b9ff60 100755 --- a/js/template/SelectorTemplate.js +++ b/js/template/SelectorTemplate.js @@ -6,14 +6,15 @@ import sanitizeText from "./sanitizeText" /** * @typedef {import("../element/SelectorElement").default} SelectorElement */ + export default class SelectorTemplate extends ITemplate { /** * Applies the style to the element. * @param {SelectorElement} selector Selector element */ - apply(selector) { - super.apply(selector) + setup(selector) { + super.setup(selector) this.applyFinishSelecting(selector) } diff --git a/js/template/StringPinTemplate.js b/js/template/StringPinTemplate.js index 75aa260..604af3e 100644 --- a/js/template/StringPinTemplate.js +++ b/js/template/StringPinTemplate.js @@ -6,6 +6,7 @@ import PinTemplate from "./PinTemplate" /** * @typedef {import("../element/PinElement").default} PinElement */ + export default class StringPinTemplate extends PinTemplate { hasInput() { @@ -28,4 +29,30 @@ export default class StringPinTemplate extends PinTemplate { ` } + + /** + * @param {PinElement} pin + */ + setup(pin) { + super.setup(pin) + const input = pin.querySelector(".ueb-pin-input-content") + this.onFocusHandler = () => { + pin.blueprint.dispatchEditTextEvent(true) + } + this.onFocusOutHandler = () => { + pin.blueprint.dispatchEditTextEvent(false) + document.getSelection().removeAllRanges() // Deselect text inside the input + } + input.addEventListener("onfocus", this.onFocusHandler) + input.addEventListener("onfocusout", this.onFocusOutHandler) + } + + /** + * @param {PinElement} pin + */ + cleanup(pin) { + super.cleanup(pin) + pin.blueprint.removeEventListener("onfocus", this.onFocusHandler) + pin.blueprint.removeEventListener("onfocusout", this.onFocusOutHandler) + } }