From 141784a3f357c485df91097a52c77cb48d679ed0 Mon Sep 17 00:00:00 2001 From: barsdeveloper Date: Tue, 5 Apr 2022 23:25:03 +0200 Subject: [PATCH] Types refactoring --- dist/ueblueprint.js | 227 ++++++++++++++-------- js/Blueprint.js | 42 ++-- js/Configuration.js | 1 + js/element/IElement.js | 53 +++-- js/element/ISelectableDraggableElement.js | 11 +- js/element/LinkElement.js | 9 +- js/element/LinkMessageElement.js | 8 +- js/element/NodeElement.js | 27 ++- js/element/PinElement.js | 38 ++-- js/element/SelectorElement.js | 7 +- js/entity/ObjectEntity.js | 8 +- js/template/BlueprintTemplate.js | 7 +- js/template/LinkMessageTemplate.js | 7 +- js/template/LinkTemplate.js | 3 +- js/template/NodeTemplate.js | 7 +- js/template/PinTemplate.js | 8 +- 16 files changed, 299 insertions(+), 164 deletions(-) diff --git a/dist/ueblueprint.js b/dist/ueblueprint.js index bf37849..73fe03a 100755 --- a/dist/ueblueprint.js +++ b/dist/ueblueprint.js @@ -39,6 +39,7 @@ class Configuration { static nodeDeleteEventName = "ueb-node-delete" static nodeDragEventName = "ueb-node-drag" static nodeDragLocalEventName = "ueb-node-drag-local" + static nodeName = (name, counter) => `${name}_${counter}` static nodeRadius = 8 // in pixel static selectAllKeyboardKey = "(bCtrl=True,Key=A)" static trackingMouseEventName = { @@ -506,27 +507,52 @@ class FastSelectionModel { * @typedef {import("../template/ITemplate").default} ITemplate */ +/** + * @template {IEntity} T + * @template {ITemplate} U + */ class IElement extends HTMLElement { static tagName = "" /** @type {Blueprint} */ - blueprint + #blueprint + get blueprint() { + return this.#blueprint + } + set blueprint(blueprint) { + this.#blueprint = blueprint; + } - /** @type {IEntity} */ - entity + /** @type {T} */ + #entity + get entity() { + return this.#entity + } + set entity(entity) { + this.#entity = entity; + } - /** @type {ITemplate} */ - template + /** @type {U} */ + #template + get template() { + return this.#template + } + set template(template) { + this.#template = template; + } /** @type {IContext[]} */ inputObjects = [] + /** + * @param {T} entity + * @param {U} template + */ constructor(entity, template) { super(); - this.blueprint = null; - this.entity = entity; - this.template = template; + this.#entity = entity; + this.#template = template; this.inputObjects = []; } @@ -535,7 +561,7 @@ class IElement extends HTMLElement { } connectedCallback() { - this.blueprint = this.closest("ueb-blueprint"); + this.#blueprint = this.closest("ueb-blueprint"); this.template.apply(this); this.inputObjects = this.createInputObjects(); } @@ -546,16 +572,16 @@ class IElement extends HTMLElement { /** @param {IElement} element */ isSameGraph(element) { - return this.blueprint && this.blueprint == element?.blueprint + return this.#blueprint && this.#blueprint == element?.blueprint } /** - * @template {IContext} T - * @param {new (...args: any[]) => T} type - * @returns {T} + * @template {IContext} V + * @param {new (...args: any[]) => V} type + * @returns {V} */ getInputObject(type) { - return /** @type {T} */ (this.inputObjects.find(object => object.constructor == type)) + return /** @type {V} */ (this.inputObjects.find(object => object.constructor == type)) } // Subclasses will want to override @@ -614,6 +640,9 @@ class SelectorTemplate extends ITemplate { // @ts-check +/** + * @extends {IElement} + */ class SelectorElement extends IElement { static tagName = "ueb-selector" @@ -621,8 +650,6 @@ class SelectorElement extends IElement { constructor() { super({}, new SelectorTemplate()); this.selectionModel = null; - /** @type {SelectorTemplate} */ - this.template; } /** @@ -649,12 +676,13 @@ class SelectorElement extends IElement { } } -customElements.define(SelectorElement.tagName, SelectorElement); +customElements.define("ueb-selector", SelectorElement); // @ts-check /** * @typedef {import("../Blueprint").default} Blueprint + * @typedef {import("../element/PinElement").default} PinElement * @typedef {import("../entity/PinReferenceEntity").default} PinReferenceEntity */ class BlueprintTemplate extends ITemplate { @@ -784,9 +812,9 @@ class BlueprintTemplate extends ITemplate { /** * - * @param {Blueprint} blueprint - * @param {PinReferenceEntity} pinReference - * @returns + * @param {Blueprint} blueprint + * @param {PinReferenceEntity} pinReference + * @returns {PinElement} */ getPin(blueprint, pinReference) { return blueprint.querySelector( @@ -1480,7 +1508,7 @@ class ObjectEntity extends IEntity { return this.Name } - getNameAndNumber() { + getNameAndCounter() { const result = this.getFullName().match(ObjectEntity.nameRegex); if (result && result.length == 3) { return [result[1], parseInt(result[2])] @@ -1488,11 +1516,11 @@ class ObjectEntity extends IEntity { } getDisplayName() { - return this.getNameAndNumber()[0] + return /** @type {String} */ (this.getNameAndCounter()[0]) } - getNodeNumber() { - return /** @type {Number} */ (this.getNameAndNumber()[1]) + getCounter() { + return /** @type {Number} */ (this.getNameAndCounter()[1]) } } @@ -2365,8 +2393,7 @@ class LinkTemplate extends ITemplate { * @param {LinkMessageElement} linkMessage */ applyLinkMessage(link, linkMessage) { - // @ts-expect-error - link.querySelectorAll(linkMessage.constructor.tagName).forEach(element => element.remove()); + link.querySelectorAll("ueb-link-message").forEach(element => element.remove()); link.appendChild(linkMessage); link.linkMessageElement = linkMessage; } @@ -2377,6 +2404,11 @@ class LinkTemplate extends ITemplate { /** * @typedef {import("./PinElement").default} PinElement * @typedef {import("./LinkMessageElement").default} LinkMessageElement + * @typedef {import("../entity/IEntity").default} IEntity + */ + +/** + * @extends {IElement} */ class LinkElement extends IElement { @@ -2452,8 +2484,6 @@ class LinkElement extends IElement { */ constructor(source, destination) { super({}, new LinkTemplate()); - /** @type {import("../template/LinkTemplate").default} */ - this.template; const self = this; this.#nodeDeleteHandler = _ => self.remove(); this.#nodeDragSourceHandler = e => self.addSourceLocation(e.detail.value); @@ -2566,7 +2596,7 @@ class LinkElement extends IElement { } } -customElements.define(LinkElement.tagName, LinkElement); +customElements.define("ueb-link", LinkElement); // @ts-check @@ -2878,17 +2908,22 @@ class MouseMoveNodes extends IMouseClickDrag { /** * @typedef {import("../template/SelectableDraggableTemplate").default} SelectableDraggableTemplate - * @typedef {import("../entity/IntegerEntity").default} IntegerEntity + * @typedef {import("../entity/IEntity").default} IEntity + */ + +/** + * @template {IEntity} T + * @template {SelectableDraggableTemplate} U + * @extends {IElement} */ class ISelectableDraggableElement extends IElement { constructor(...args) { + // @ts-expect-error super(...args); this.dragObject = null; this.location = [0, 0]; this.selected = false; - /** @type {SelectableDraggableTemplate} */ - this.template; let self = this; this.dragHandler = (e) => { @@ -2982,15 +3017,16 @@ class LinkMessageTemplate extends ITemplate { */ apply(linkMessage) { super.apply(linkMessage); - const linkMessageSetup = _ => linkMessage.querySelector(".ueb-link-message").innerText = linkMessage.message( + const linkMessageSetup = _ => + /** @type {HTMLElement} */(linkMessage.querySelector(".ueb-link-message")).innerText = linkMessage.message( linkMessage.linkElement.sourcePin, linkMessage.linkElement.destinationPin ); - linkMessage.linkElement = linkMessage.closest(LinkElement.tagName); + linkMessage.linkElement = linkMessage.closest("ueb-link"); if (linkMessage.linkElement) { linkMessageSetup(); } else { - window.customElements.whenDefined(linkMessage.constructor.tagName).then(linkMessage); + window.customElements.whenDefined("ueb-link-message").then(linkMessage); } } @@ -3003,6 +3039,10 @@ class LinkMessageTemplate extends ITemplate { * @typedef {import("./LinkElement").default} LinkElement * @typedef {(sourcePin: PinElement, destinationPin: PinElement) => String} LinkRetrieval */ + +/** + * @extends {IElement} + */ class LinkMessageElement extends IElement { static tagName = "ueb-link-message" @@ -3044,7 +3084,7 @@ class LinkMessageElement extends IElement { /** @type {String} */ icon - /** @type {String} */ + /** @type {LinkRetrieval} */ message /** @type {LinkElement} */ linkElement @@ -3057,7 +3097,7 @@ class LinkMessageElement extends IElement { } -customElements.define(LinkMessageElement.tagName, LinkMessageElement); +customElements.define("ueb-link-message", LinkMessageElement); // @ts-check @@ -3318,8 +3358,13 @@ class StringPinTemplate extends PinTemplate { /** * @typedef {import("../entity/GuidEntity").default} GuidEntity * @typedef {import("../entity/PinEntity").default} PinEntity + * @typedef {import("../entity/PinReferenceEntity").default} PinReferenceEntity * @typedef {import("./NodeElement").default} NodeElement */ + +/** + * @extends {IElement} + */ class PinElement extends IElement { static tagName = "ueb-pin" @@ -3344,12 +3389,6 @@ class PinElement extends IElement { entity, new (PinElement.#typeTemplateMap[entity.getType()] ?? PinTemplate)() ); - - /** @type {PinEntity} */ - this.entity; - - /** @type {PinTemplate} */ - this.template; } connectedCallback() { @@ -3414,10 +3453,6 @@ class PinElement extends IElement { return this.#color } - /** - * Returns The exact location where the link originates from or arrives at. - * @returns {Number[]} The location array - */ getLinkLocation() { return this.template.getLinkLocation(this) } @@ -3430,9 +3465,7 @@ class PinElement extends IElement { } getLinks() { - return this.entity.LinkedTo?.map(pinReference => - pinReference - ) ?? [] + return this.entity.LinkedTo ?? [] } /** @@ -3450,9 +3483,26 @@ class PinElement extends IElement { this.entity.unlinkFrom(targetPinElement.nodeElement.getNodeName(), targetPinElement.entity); this.template.applyConnected(this); } + + /** + * + * @param {PinElement} originalPinElement + * @param {PinReferenceEntity} newReference + */ + redirectLink(originalPinElement, newReference) { + const index = this.entity.LinkedTo.findIndex(pinReference => + pinReference.objectName.toString() == originalPinElement.getPinName() + && pinReference.pinGuid == originalPinElement.entity.PinId + ); + if (index >= 0) { + this.entity.LinkedTo[index] = newReference; + return true + } + return false + } } -customElements.define(PinElement.tagName, PinElement); +customElements.define("ueb-pin", PinElement); // @ts-check @@ -3526,9 +3576,8 @@ class NodeTemplate extends SelectableDraggableTemplate { if (node.selected) { node.classList.add("ueb-selected"); } - const name = node.entity.getNameAndNumber(); - node.dataset.name = sanitizeText(name[0]); - node.dataset.count = sanitizeText(name[1]); + const nodeName = node.entity.getFullName(); + node.dataset.name = sanitizeText(nodeName); if (node.entity.AdvancedPinDisplay) { node.dataset.advancedDisplay = node.entity.AdvancedPinDisplay.toString(); } @@ -3548,12 +3597,15 @@ class NodeTemplate extends SelectableDraggableTemplate { * @returns {NodeListOf} */ getPinElements(node) { - return node.querySelectorAll(PinElement.tagName) + return node.querySelectorAll("ueb-pin") } } // @ts-check +/** + * @extends {ISelectableDraggableElement} + */ class NodeElement extends ISelectableDraggableElement { static tagName = "ueb-node" @@ -3563,10 +3615,6 @@ class NodeElement extends ISelectableDraggableElement { */ constructor(entity) { super(entity, new NodeTemplate()); - /** @type {ObjectEntity} */ - this.entity; - /** @type {NodeTemplate} */ - this.template; this.dragLinkObjects = []; super.setLocation([this.entity.NodePosX.value, this.entity.NodePosY.value]); } @@ -3585,6 +3633,23 @@ class NodeElement extends ISelectableDraggableElement { return this.entity.getFullName() } + /** + * @param {String} name + */ + rename(name) { + if (this.entity.Name == name) { + return false + } + this.getPinElements().forEach(sourcePinElement => + sourcePinElement.getLinks().forEach(targetPinReference => + this.blueprint.getPin(targetPinReference).redirectLink(sourcePinElement, new PinReferenceEntity({ + objectName: name, + pinGuid: sourcePinElement.entity.PinId, + })) + )); + this.entity.Name = name; + } + getPinElements() { return this.template.getPinElements(this) } @@ -3619,7 +3684,7 @@ class NodeElement extends ISelectableDraggableElement { } } -customElements.define(NodeElement.tagName, NodeElement); +customElements.define("ueb-node", NodeElement); // @ts-check @@ -3749,13 +3814,15 @@ class Unfocus extends IContext { * @typedef {import("./entity/GuidEntity").default} GuidEntity * @typedef {import("./entity/PinReferenceEntity").default} PinReferenceEntity */ + +/** + * @extends {IElement} + */ class Blueprint extends IElement { static tagName = "ueb-blueprint" /** @type {Number[]} */ #additional - /** @type {Number[]} */ - #translateValue get additional() { return this.#additional } @@ -3763,12 +3830,16 @@ class Blueprint extends IElement { value[0] = Math.abs(value[0]); value[1] = Math.abs(value[1]); } + /** @type {Number[]} */ + #translateValue get translateValue() { return this.#translateValue } set translateValue(value) { this.#translateValue = value; } + /** @type {Map} */ + #nodeNameCounter = new Map() /** @type {Number} */ gridSize /** @type {NodeElement[]}" */ @@ -3814,8 +3885,6 @@ class Blueprint extends IElement { */ constructor(settings = new Configuration()) { super({}, new BlueprintTemplate()); - /** @type {BlueprintTemplate} */ - this.template; /** @type {Number} */ this.gridSize = Configuration.gridSize; /** @type {Number[]} */ @@ -4056,6 +4125,9 @@ class Blueprint extends IElement { return parseFloat(getComputedStyle(this.gridElement).getPropertyValue("--ueb-scale")) } + /** + * @param {Number[]} position + */ compensateTranslation(position) { position[0] -= this.translateValue[0]; position[1] -= this.translateValue[1]; @@ -4119,19 +4191,16 @@ class Blueprint extends IElement { addGraphElement(...graphElements) { graphElements.forEach(element => { if (element instanceof NodeElement && !this.nodes.includes(element)) { - const nameAndCount = element.entity.getNameAndNumber(); + const [nodeName, nodeCount] = element.entity.getNameAndCounter(); // Node with the same name and number exists already - let maximumCount = 0; - { - ( - this.nodesContainerElement?.querySelectorAll(`ueb-node[data-name="${nameAndCount[0]}"]`) - ?? this.nodes - ).forEach(node => maximumCount = Math.max( - maximumCount, - /** @type {NodeElement} node */(node).entity.getNodeNumber()) - ); + const homonymNode = this.nodes.find(node => { + const [currentName, currentCount] = node.entity.getNameAndCounter(); + return currentName == nodeName && currentCount == nodeName + }); + if (homonymNode) { + this.#nodeNameCounter[nodeName] = (this.#nodeNameCounter[nodeName] ?? -1) + 1; + homonymNode.dataset.name = Configuration.nodeName(nodeName, this.#nodeNameCounter[nodeName]); } - element.entity.Name = `${nameAndCount[0]}_${maximumCount + 1}`; this.nodes.push(element); } else if (element instanceof LinkElement && !this.links.includes(element)) { this.links.push(element); @@ -4146,14 +4215,14 @@ class Blueprint extends IElement { removeGraphElement(...graphElements) { let removed = false; graphElements.forEach(element => { - if (element.closest(Blueprint.tagName) == this) { + if (element.closest("ueb-blueprint") == this) { element.remove(); removed = false; } }); if (removed) { - this.nodes = /** @type {NodeElement[]} */ ([...this.querySelectorAll(NodeElement.tagName)]); - this.links = /** @type {LinkElement[]} */ ([...this.querySelectorAll(LinkElement.tagName)]); + this.nodes = /** @type {NodeElement[]} */ ([...this.querySelectorAll("ueb-node")]); + this.links = /** @type {LinkElement[]} */ ([...this.querySelectorAll("ueb-link")]); } } @@ -4180,7 +4249,7 @@ class Blueprint extends IElement { } } -customElements.define(Blueprint.tagName, Blueprint); +customElements.define("ueb-blueprint", Blueprint); // @ts-check diff --git a/js/Blueprint.js b/js/Blueprint.js index c0e686e..2fef5c3 100755 --- a/js/Blueprint.js +++ b/js/Blueprint.js @@ -23,13 +23,15 @@ import Zoom from "./input/mouse/Zoom" * @typedef {import("./entity/GuidEntity").default} GuidEntity * @typedef {import("./entity/PinReferenceEntity").default} PinReferenceEntity */ + +/** + * @extends {IElement} + */ export default class Blueprint extends IElement { static tagName = "ueb-blueprint" /** @type {Number[]} */ #additional - /** @type {Number[]} */ - #translateValue get additional() { return this.#additional } @@ -37,12 +39,16 @@ export default class Blueprint extends IElement { value[0] = Math.abs(value[0]) value[1] = Math.abs(value[1]) } + /** @type {Number[]} */ + #translateValue get translateValue() { return this.#translateValue } set translateValue(value) { this.#translateValue = value } + /** @type {Map} */ + #nodeNameCounter = new Map() /** @type {Number} */ gridSize /** @type {NodeElement[]}" */ @@ -88,8 +94,6 @@ export default class Blueprint extends IElement { */ constructor(settings = new Configuration()) { super({}, new BlueprintTemplate()) - /** @type {BlueprintTemplate} */ - this.template /** @type {Number} */ this.gridSize = Configuration.gridSize /** @type {Number[]} */ @@ -330,6 +334,9 @@ export default class Blueprint extends IElement { return parseFloat(getComputedStyle(this.gridElement).getPropertyValue("--ueb-scale")) } + /** + * @param {Number[]} position + */ compensateTranslation(position) { position[0] -= this.translateValue[0] position[1] -= this.translateValue[1] @@ -393,19 +400,16 @@ export default class Blueprint extends IElement { addGraphElement(...graphElements) { graphElements.forEach(element => { if (element instanceof NodeElement && !this.nodes.includes(element)) { - const nameAndCount = element.entity.getNameAndNumber() + const [nodeName, nodeCount] = element.entity.getNameAndCounter() // Node with the same name and number exists already - let maximumCount = 0 - { - ( - this.nodesContainerElement?.querySelectorAll(`ueb-node[data-name="${nameAndCount[0]}"]`) - ?? this.nodes - ).forEach(node => maximumCount = Math.max( - maximumCount, - /** @type {NodeElement} node */(node).entity.getNodeNumber()) - ) + const homonymNode = this.nodes.find(node => { + const [currentName, currentCount] = node.entity.getNameAndCounter() + return currentName == nodeName && currentCount == nodeName + }) + if (homonymNode) { + this.#nodeNameCounter[nodeName] = (this.#nodeNameCounter[nodeName] ?? -1) + 1 + homonymNode.dataset.name = Configuration.nodeName(nodeName, this.#nodeNameCounter[nodeName]) } - element.entity.Name = `${nameAndCount[0]}_${maximumCount + 1}` this.nodes.push(element) } else if (element instanceof LinkElement && !this.links.includes(element)) { this.links.push(element) @@ -420,14 +424,14 @@ export default class Blueprint extends IElement { removeGraphElement(...graphElements) { let removed = false graphElements.forEach(element => { - if (element.closest(Blueprint.tagName) == this) { + if (element.closest("ueb-blueprint") == this) { element.remove() removed = false } }) if (removed) { - this.nodes = /** @type {NodeElement[]} */ ([...this.querySelectorAll(NodeElement.tagName)]) - this.links = /** @type {LinkElement[]} */ ([...this.querySelectorAll(LinkElement.tagName)]) + this.nodes = /** @type {NodeElement[]} */ ([...this.querySelectorAll("ueb-node")]) + this.links = /** @type {LinkElement[]} */ ([...this.querySelectorAll("ueb-link")]) } } @@ -454,4 +458,4 @@ export default class Blueprint extends IElement { } } -customElements.define(Blueprint.tagName, Blueprint) +customElements.define("ueb-blueprint", Blueprint) diff --git a/js/Configuration.js b/js/Configuration.js index 1533de6..6aa9b7f 100755 --- a/js/Configuration.js +++ b/js/Configuration.js @@ -39,6 +39,7 @@ export default class Configuration { static nodeDeleteEventName = "ueb-node-delete" static nodeDragEventName = "ueb-node-drag" static nodeDragLocalEventName = "ueb-node-drag-local" + static nodeName = (name, counter) => `${name}_${counter}` static nodeRadius = 8 // in pixel static selectAllKeyboardKey = "(bCtrl=True,Key=A)" static trackingMouseEventName = { diff --git a/js/element/IElement.js b/js/element/IElement.js index 32d9f3c..e6a3896 100644 --- a/js/element/IElement.js +++ b/js/element/IElement.js @@ -7,27 +7,52 @@ * @typedef {import("../template/ITemplate").default} ITemplate */ +/** + * @template {IEntity} T + * @template {ITemplate} U + */ export default class IElement extends HTMLElement { static tagName = "" /** @type {Blueprint} */ - blueprint + #blueprint + get blueprint() { + return this.#blueprint + } + set blueprint(blueprint) { + this.#blueprint = blueprint + } - /** @type {IEntity} */ - entity + /** @type {T} */ + #entity + get entity() { + return this.#entity + } + set entity(entity) { + this.#entity = entity + } - /** @type {ITemplate} */ - template + /** @type {U} */ + #template + get template() { + return this.#template + } + set template(template) { + this.#template = template + } /** @type {IContext[]} */ inputObjects = [] + /** + * @param {T} entity + * @param {U} template + */ constructor(entity, template) { super() - this.blueprint = null - this.entity = entity - this.template = template + this.#entity = entity + this.#template = template this.inputObjects = [] } @@ -36,7 +61,7 @@ export default class IElement extends HTMLElement { } connectedCallback() { - this.blueprint = this.closest("ueb-blueprint") + this.#blueprint = this.closest("ueb-blueprint") this.template.apply(this) this.inputObjects = this.createInputObjects() } @@ -47,16 +72,16 @@ export default class IElement extends HTMLElement { /** @param {IElement} element */ isSameGraph(element) { - return this.blueprint && this.blueprint == element?.blueprint + return this.#blueprint && this.#blueprint == element?.blueprint } /** - * @template {IContext} T - * @param {new (...args: any[]) => T} type - * @returns {T} + * @template {IContext} V + * @param {new (...args: any[]) => V} type + * @returns {V} */ getInputObject(type) { - return /** @type {T} */ (this.inputObjects.find(object => object.constructor == type)) + return /** @type {V} */ (this.inputObjects.find(object => object.constructor == type)) } // Subclasses will want to override diff --git a/js/element/ISelectableDraggableElement.js b/js/element/ISelectableDraggableElement.js index 1ff2731..7bc6840 100644 --- a/js/element/ISelectableDraggableElement.js +++ b/js/element/ISelectableDraggableElement.js @@ -6,17 +6,22 @@ import MouseMoveNodes from "../input/mouse/MouseMoveNodes" /** * @typedef {import("../template/SelectableDraggableTemplate").default} SelectableDraggableTemplate - * @typedef {import("../entity/IntegerEntity").default} IntegerEntity + * @typedef {import("../entity/IEntity").default} IEntity + */ + +/** + * @template {IEntity} T + * @template {SelectableDraggableTemplate} U + * @extends {IElement} */ export default class ISelectableDraggableElement extends IElement { constructor(...args) { + // @ts-expect-error super(...args) this.dragObject = null this.location = [0, 0] this.selected = false - /** @type {SelectableDraggableTemplate} */ - this.template let self = this this.dragHandler = (e) => { diff --git a/js/element/LinkElement.js b/js/element/LinkElement.js index 826e5c9..138e6e3 100644 --- a/js/element/LinkElement.js +++ b/js/element/LinkElement.js @@ -7,6 +7,11 @@ import LinkTemplate from "../template/LinkTemplate" /** * @typedef {import("./PinElement").default} PinElement * @typedef {import("./LinkMessageElement").default} LinkMessageElement + * @typedef {import("../entity/IEntity").default} IEntity + */ + +/** + * @extends {IElement} */ export default class LinkElement extends IElement { @@ -82,8 +87,6 @@ export default class LinkElement extends IElement { */ constructor(source, destination) { super({}, new LinkTemplate()) - /** @type {import("../template/LinkTemplate").default} */ - this.template const self = this this.#nodeDeleteHandler = _ => self.remove() this.#nodeDragSourceHandler = e => self.addSourceLocation(e.detail.value) @@ -196,4 +199,4 @@ export default class LinkElement extends IElement { } } -customElements.define(LinkElement.tagName, LinkElement) +customElements.define("ueb-link", LinkElement) diff --git a/js/element/LinkMessageElement.js b/js/element/LinkMessageElement.js index 129f376..9ac2e45 100644 --- a/js/element/LinkMessageElement.js +++ b/js/element/LinkMessageElement.js @@ -8,6 +8,10 @@ import LinkMessageTemplate from "../template/LinkMessageTemplate" * @typedef {import("./LinkElement").default} LinkElement * @typedef {(sourcePin: PinElement, destinationPin: PinElement) => String} LinkRetrieval */ + +/** + * @extends {IElement} + */ export default class LinkMessageElement extends IElement { static tagName = "ueb-link-message" @@ -49,7 +53,7 @@ export default class LinkMessageElement extends IElement { /** @type {String} */ icon - /** @type {String} */ + /** @type {LinkRetrieval} */ message /** @type {LinkElement} */ linkElement @@ -62,4 +66,4 @@ export default class LinkMessageElement extends IElement { } -customElements.define(LinkMessageElement.tagName, LinkMessageElement) +customElements.define("ueb-link-message", LinkMessageElement) diff --git a/js/element/NodeElement.js b/js/element/NodeElement.js index ed122ef..8eee9dc 100644 --- a/js/element/NodeElement.js +++ b/js/element/NodeElement.js @@ -6,7 +6,11 @@ import NodeTemplate from "../template/NodeTemplate" import ObjectEntity from "../entity/ObjectEntity" import PinEntity from "../entity/PinEntity" import SerializerFactory from "../serialization/SerializerFactory" +import PinReferenceEntity from "../entity/PinReferenceEntity" +/** + * @extends {ISelectableDraggableElement} + */ export default class NodeElement extends ISelectableDraggableElement { static tagName = "ueb-node" @@ -16,10 +20,6 @@ export default class NodeElement extends ISelectableDraggableElement { */ constructor(entity) { super(entity, new NodeTemplate()) - /** @type {ObjectEntity} */ - this.entity - /** @type {NodeTemplate} */ - this.template this.dragLinkObjects = [] super.setLocation([this.entity.NodePosX.value, this.entity.NodePosY.value]) } @@ -38,6 +38,23 @@ export default class NodeElement extends ISelectableDraggableElement { return this.entity.getFullName() } + /** + * @param {String} name + */ + rename(name) { + if (this.entity.Name == name) { + return false + } + this.getPinElements().forEach(sourcePinElement => + sourcePinElement.getLinks().forEach(targetPinReference => + this.blueprint.getPin(targetPinReference).redirectLink(sourcePinElement, new PinReferenceEntity({ + objectName: name, + pinGuid: sourcePinElement.entity.PinId, + })) + )) + this.entity.Name = name + } + getPinElements() { return this.template.getPinElements(this) } @@ -72,4 +89,4 @@ export default class NodeElement extends ISelectableDraggableElement { } } -customElements.define(NodeElement.tagName, NodeElement) +customElements.define("ueb-node", NodeElement) diff --git a/js/element/PinElement.js b/js/element/PinElement.js index 5cd5191..e7f850c 100644 --- a/js/element/PinElement.js +++ b/js/element/PinElement.js @@ -9,8 +9,13 @@ import StringPinTemplate from "../template/StringPinTemplate" /** * @typedef {import("../entity/GuidEntity").default} GuidEntity * @typedef {import("../entity/PinEntity").default} PinEntity + * @typedef {import("../entity/PinReferenceEntity").default} PinReferenceEntity * @typedef {import("./NodeElement").default} NodeElement */ + +/** + * @extends {IElement} + */ export default class PinElement extends IElement { static tagName = "ueb-pin" @@ -35,12 +40,6 @@ export default class PinElement extends IElement { entity, new (PinElement.#typeTemplateMap[entity.getType()] ?? PinTemplate)() ) - - /** @type {PinEntity} */ - this.entity - - /** @type {PinTemplate} */ - this.template } connectedCallback() { @@ -105,10 +104,6 @@ export default class PinElement extends IElement { return this.#color } - /** - * Returns The exact location where the link originates from or arrives at. - * @returns {Number[]} The location array - */ getLinkLocation() { return this.template.getLinkLocation(this) } @@ -121,9 +116,7 @@ export default class PinElement extends IElement { } getLinks() { - return this.entity.LinkedTo?.map(pinReference => - pinReference - ) ?? [] + return this.entity.LinkedTo ?? [] } /** @@ -141,6 +134,23 @@ export default class PinElement extends IElement { this.entity.unlinkFrom(targetPinElement.nodeElement.getNodeName(), targetPinElement.entity) this.template.applyConnected(this) } + + /** + * + * @param {PinElement} originalPinElement + * @param {PinReferenceEntity} newReference + */ + redirectLink(originalPinElement, newReference) { + const index = this.entity.LinkedTo.findIndex(pinReference => + pinReference.objectName.toString() == originalPinElement.getPinName() + && pinReference.pinGuid == originalPinElement.entity.PinId + ) + if (index >= 0) { + this.entity.LinkedTo[index] = newReference + return true + } + return false + } } -customElements.define(PinElement.tagName, PinElement) +customElements.define("ueb-pin", PinElement) diff --git a/js/element/SelectorElement.js b/js/element/SelectorElement.js index 21fb96d..a41383d 100644 --- a/js/element/SelectorElement.js +++ b/js/element/SelectorElement.js @@ -4,6 +4,9 @@ import FastSelectionModel from "../selection/FastSelectionModel" import IElement from "./IElement" import SelectorTemplate from "../template/SelectorTemplate" +/** + * @extends {IElement} + */ export default class SelectorElement extends IElement { static tagName = "ueb-selector" @@ -11,8 +14,6 @@ export default class SelectorElement extends IElement { constructor() { super({}, new SelectorTemplate()) this.selectionModel = null - /** @type {SelectorTemplate} */ - this.template } /** @@ -39,4 +40,4 @@ export default class SelectorElement extends IElement { } } -customElements.define(SelectorElement.tagName, SelectorElement) +customElements.define("ueb-selector", SelectorElement) diff --git a/js/entity/ObjectEntity.js b/js/entity/ObjectEntity.js index 89b27cb..9594b8f 100755 --- a/js/entity/ObjectEntity.js +++ b/js/entity/ObjectEntity.js @@ -53,7 +53,7 @@ export default class ObjectEntity extends IEntity { return this.Name } - getNameAndNumber() { + getNameAndCounter() { const result = this.getFullName().match(ObjectEntity.nameRegex) if (result && result.length == 3) { return [result[1], parseInt(result[2])] @@ -61,10 +61,10 @@ export default class ObjectEntity extends IEntity { } getDisplayName() { - return this.getNameAndNumber()[0] + return /** @type {String} */ (this.getNameAndCounter()[0]) } - getNodeNumber() { - return /** @type {Number} */ (this.getNameAndNumber()[1]) + getCounter() { + return /** @type {Number} */ (this.getNameAndCounter()[1]) } } diff --git a/js/template/BlueprintTemplate.js b/js/template/BlueprintTemplate.js index 2fc8baf..b3a5a54 100755 --- a/js/template/BlueprintTemplate.js +++ b/js/template/BlueprintTemplate.js @@ -8,6 +8,7 @@ import SelectorElement from "../element/SelectorElement" /** * @typedef {import("../Blueprint").default} Blueprint + * @typedef {import("../element/PinElement").default} PinElement * @typedef {import("../entity/PinReferenceEntity").default} PinReferenceEntity */ export default class BlueprintTemplate extends ITemplate { @@ -137,9 +138,9 @@ export default class BlueprintTemplate extends ITemplate { /** * - * @param {Blueprint} blueprint - * @param {PinReferenceEntity} pinReference - * @returns + * @param {Blueprint} blueprint + * @param {PinReferenceEntity} pinReference + * @returns {PinElement} */ getPin(blueprint, pinReference) { return blueprint.querySelector( diff --git a/js/template/LinkMessageTemplate.js b/js/template/LinkMessageTemplate.js index bf4b5ba..fa7dc7b 100644 --- a/js/template/LinkMessageTemplate.js +++ b/js/template/LinkMessageTemplate.js @@ -26,15 +26,16 @@ export default class LinkMessageTemplate extends ITemplate { */ apply(linkMessage) { const a = super.apply(linkMessage) - const linkMessageSetup = _ => linkMessage.querySelector(".ueb-link-message").innerText = linkMessage.message( + const linkMessageSetup = _ => + /** @type {HTMLElement} */(linkMessage.querySelector(".ueb-link-message")).innerText = linkMessage.message( linkMessage.linkElement.sourcePin, linkMessage.linkElement.destinationPin ) - linkMessage.linkElement = linkMessage.closest(LinkElement.tagName) + linkMessage.linkElement = linkMessage.closest("ueb-link") if (linkMessage.linkElement) { linkMessageSetup() } else { - window.customElements.whenDefined(linkMessage.constructor.tagName).then(linkMessage) + window.customElements.whenDefined("ueb-link-message").then(linkMessage) } } diff --git a/js/template/LinkTemplate.js b/js/template/LinkTemplate.js index e3fa9d2..44bdc88 100755 --- a/js/template/LinkTemplate.js +++ b/js/template/LinkTemplate.js @@ -163,8 +163,7 @@ export default class LinkTemplate extends ITemplate { * @param {LinkMessageElement} linkMessage */ applyLinkMessage(link, linkMessage) { - // @ts-expect-error - link.querySelectorAll(linkMessage.constructor.tagName).forEach(element => element.remove()) + link.querySelectorAll("ueb-link-message").forEach(element => element.remove()) link.appendChild(linkMessage) link.linkMessageElement = linkMessage } diff --git a/js/template/NodeTemplate.js b/js/template/NodeTemplate.js index d1dabc5..63f9e5a 100755 --- a/js/template/NodeTemplate.js +++ b/js/template/NodeTemplate.js @@ -46,9 +46,8 @@ export default class NodeTemplate extends SelectableDraggableTemplate { if (node.selected) { node.classList.add("ueb-selected") } - const name = node.entity.getNameAndNumber() - node.dataset.name = sanitizeText(name[0]) - node.dataset.count = sanitizeText(name[1]) + const nodeName = node.entity.getFullName() + node.dataset.name = sanitizeText(nodeName) if (node.entity.AdvancedPinDisplay) { node.dataset.advancedDisplay = node.entity.AdvancedPinDisplay.toString() } @@ -68,6 +67,6 @@ export default class NodeTemplate extends SelectableDraggableTemplate { * @returns {NodeListOf} */ getPinElements(node) { - return node.querySelectorAll(PinElement.tagName) + return node.querySelectorAll("ueb-pin") } } diff --git a/js/template/PinTemplate.js b/js/template/PinTemplate.js index bce3052..0f3f844 100755 --- a/js/template/PinTemplate.js +++ b/js/template/PinTemplate.js @@ -17,9 +17,7 @@ export default class PinTemplate extends ITemplate { } /** - * Computes the html content of the pin. - * @param {PinElement} pin html element - * @returns The result html + * @param {PinElement} pin */ render(pin) { if (pin.isInput()) { @@ -57,8 +55,7 @@ export default class PinTemplate extends ITemplate { } /** - * Applies the style to the element. - * @param {PinElement} pin element of the graph + * @param {PinElement} pin */ apply(pin) { super.apply(pin) @@ -84,7 +81,6 @@ export default class PinTemplate extends ITemplate { } /** - * Applies the connection style to the element. * @param {PinElement} pin */ applyConnected(pin) {