From 8bca6dcff416c2feed74bc820fce84dd259f6572 Mon Sep 17 00:00:00 2001 From: barsdeveloper Date: Thu, 10 Mar 2022 22:31:47 +0100 Subject: [PATCH] Links wip --- dist/ueblueprint.js | 120 +++++++++++++++++++++++++++++++----- js/element/LinkElement.js | 25 ++++++++ js/element/NodeElement.js | 4 ++ js/element/PinElement.js | 29 ++++++++- js/entity/ObjectEntity.js | 2 +- js/entity/PinEntity.js | 42 +++++++++++-- js/template/LinkTemplate.js | 11 ++-- js/template/NodeTemplate.js | 2 +- js/template/PinTemplate.js | 5 ++ 9 files changed, 210 insertions(+), 30 deletions(-) diff --git a/dist/ueblueprint.js b/dist/ueblueprint.js index 990104e..1954945 100755 --- a/dist/ueblueprint.js +++ b/dist/ueblueprint.js @@ -1107,18 +1107,50 @@ class PinEntity extends IEntity { } /** - * @param {PinReferenceEntity} pinReferenceEntity + * @param {String} targetObjectName + * @param {PinEntity} targetPinEntity */ - connectTo(pinReferenceEntity) { + linkTo(targetObjectName, targetPinEntity) { /** @type {PinReferenceEntity[]} */ this.LinkedTo; - this.LinkedTo.forEach(reference => { + const pinExists = !this.LinkedTo.find( + /** @type {PinReferenceEntity} */ + pinReferenceEntity => { + return pinReferenceEntity.objectName == targetObjectName + && pinReferenceEntity.pinGuid == targetPinEntity.PinId + }); + if (pinExists) { + this.LinkedTo.push(new PinReferenceEntity({ + objectName: targetObjectName, + pinGuid: targetPinEntity.PinId + })); + return true + } + return false + } - }); + /** + * @param {String} targetObjectName + * @param {PinEntity} targetPinEntity + */ + unlinkFrom(targetObjectName, targetPinEntity) { + /** @type {PinReferenceEntity[]} */ + this.LinkedTo; + const indexElement = this.LinkedTo.findIndex( + /** @type {PinReferenceEntity} */ + pinReferenceEntity => { + return pinReferenceEntity.objectName == targetObjectName + && pinReferenceEntity.pinGuid == targetPinEntity.PinId + }); + if (indexElement >= 0) { + this.LinkedTo.splice(indexElement, 1); + return true + } + return false } getType() { - return this.PinType.PinCategory ?? "object" + return this.PinType.PinCategory } } @@ -1152,7 +1184,7 @@ class ObjectEntity extends IEntity { /** * @returns {String} The name of the node */ - getNodeDisplayName() { + getName() { return this.Name } } @@ -1644,7 +1676,7 @@ class LinkTemplate extends ITemplate { return x => a / x + q } - /* + /** * Returns a function performing a clamped line passing through two points. It is clamped after and before the * points. It is easier explained with an example. * b ______ @@ -1674,7 +1706,7 @@ class LinkTemplate extends ITemplate { static c2DecreasingValue = LinkTemplate.decreasingValue(-0.06, [500, 130]) - static c1Clamped = LinkTemplate.clampedLine([0, 100], [100, 30]) + static c2Clamped = LinkTemplate.clampedLine([0, 100], [200, 30]) /** * Computes the html content of the target element. @@ -1768,11 +1800,8 @@ class LinkTemplate extends ITemplate { : 10 ) * fillRatio; - let c2 = LinkTemplate.clampedLine([0, 100], [100, 30])(xInverted ? -dx : dx) + start; - c2 = Math.min( - c2, - LinkTemplate.c2DecreasingValue(width) - ); + let c2 = LinkTemplate.c2Clamped(xInverted ? -dx : dx) + start; + c2 = Math.min(c2, LinkTemplate.c2DecreasingValue(width)); const d = Configuration.linkRightSVGPath(start, c1, c2); // TODO move to CSS when Firefox will support property d and css will have enough functions link.pathElement.setAttribute("d", d); @@ -1829,6 +1858,19 @@ class LinkElement extends IElement { if (destination) { this.setDestinationPin(destination); } + if (source && destination) { + this.#linkPins(); + } + } + + #linkPins() { + this.#source.linkTo(this.#destination); + this.#destination.linkTo(this.#source); + } + + #unlinkPins() { + this.#source.unlinkFrom(this.#destination); + this.#destination.unlinkFrom(this.#source); } /** @@ -1905,6 +1947,9 @@ class LinkElement extends IElement { const nodeElement = this.#source.getNodeElement(); nodeElement.removeEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler); nodeElement.removeEventListener(Configuration.nodeDragLocalEventName, this.#nodeDragSourceHandler); + if (this.#destination) { + this.#unlinkPins(); + } } this.#source = pin; if (this.#source) { @@ -1913,6 +1958,9 @@ class LinkElement extends IElement { nodeElement.addEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler); nodeElement.addEventListener(Configuration.nodeDragLocalEventName, this.#nodeDragSourceHandler); this.setSourceLocation(); + if (this.#destination) { + this.#linkPins(); + } } } @@ -1931,6 +1979,9 @@ class LinkElement extends IElement { const nodeElement = this.#destination.getNodeElement(); nodeElement.removeEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler); nodeElement.removeEventListener(Configuration.nodeDragLocalEventName, this.#nodeDragDestinatonHandler); + if (this.#source) { + this.#unlinkPins(); + } } this.#destination = pin; if (this.#destination) { @@ -1938,6 +1989,9 @@ class LinkElement extends IElement { nodeElement.addEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler); nodeElement.addEventListener(Configuration.nodeDragLocalEventName, this.#nodeDragDestinatonHandler); this.setDestinationLocation(); + if (this.#source) { + this.#linkPins(); + } } } @@ -2520,6 +2574,7 @@ class MouseCreateLink extends IMouseClickDrag { } /** + * @typedef {import("../element/NodeElement").default} NodeElement * @typedef {import("../element/PinElement").default} PinElement */ class PinTemplate extends ITemplate { @@ -2555,6 +2610,10 @@ class PinTemplate extends ITemplate { pin.isConnected() ? "ueb-pin-fill" : null ); pin.clickableElement = pin; + pin.nodeElement = pin.closest("ueb-node"); + if (!pin.nodeElement) { + window.customElements.whenDefined(linkMessage.constructor.tagName).then(linkMessage); + } } /** @@ -2580,10 +2639,16 @@ class PinTemplate extends ITemplate { } } +/** + * @typedef {import("./NodeElement").default} NodeElement + */ class PinElement extends IElement { static tagName = "ueb-pin" + /** @type {NodeElement} */ + nodeElement + /** @type {HTMLElement} */ clickableElement @@ -2615,10 +2680,17 @@ class PinElement extends IElement { /** * @returns {String} */ - getPinDisplayName() { + getPinName() { return this.entity.PinName } + /** + * @returns {String} + */ + getPinDisplayName() { + return this.entity.PinFriendlyName + } + isInput() { return this.entity.isInput() } @@ -2654,6 +2726,20 @@ class PinElement extends IElement { getNodeElement() { return this.closest("ueb-node") } + + /** + * @param {PinElement} targetPinElement + */ + linkTo(targetPinElement) { + this.entity.linkTo(targetPinElement.nodeElement.getNodeName(), targetPinElement.entity); + } + + /** + * @param {PinElement} targetPinElement + */ + unlinkFrom(targetPinElement) { + this.entity.unlinkFrom(targetPinElement.nodeElement.getNodeName(), targetPinElement.entity); + } } customElements.define(PinElement.tagName, PinElement); @@ -2702,7 +2788,7 @@ class NodeTemplate extends SelectableDraggableTemplate {
- ${sanitizeText(node.entity.getNodeDisplayName())} + ${sanitizeText(node.entity.getName())}
@@ -2760,6 +2846,10 @@ class NodeElement extends ISelectableDraggableElement { this.dispatchDeleteEvent(); } + getNodeName() { + return this.entity.getName() + } + /** * @returns {PinEntity[]} */ diff --git a/js/element/LinkElement.js b/js/element/LinkElement.js index 56eabf6..3e7c482 100644 --- a/js/element/LinkElement.js +++ b/js/element/LinkElement.js @@ -42,6 +42,19 @@ export default class LinkElement extends IElement { if (destination) { this.setDestinationPin(destination) } + if (source && destination) { + this.#linkPins() + } + } + + #linkPins() { + this.#source.linkTo(this.#destination) + this.#destination.linkTo(this.#source) + } + + #unlinkPins() { + this.#source.unlinkFrom(this.#destination) + this.#destination.unlinkFrom(this.#source) } /** @@ -118,6 +131,9 @@ export default class LinkElement extends IElement { const nodeElement = this.#source.getNodeElement() nodeElement.removeEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler) nodeElement.removeEventListener(Configuration.nodeDragLocalEventName, this.#nodeDragSourceHandler) + if (this.#destination) { + this.#unlinkPins() + } } this.#source = pin if (this.#source) { @@ -126,6 +142,9 @@ export default class LinkElement extends IElement { nodeElement.addEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler) nodeElement.addEventListener(Configuration.nodeDragLocalEventName, this.#nodeDragSourceHandler) this.setSourceLocation() + if (this.#destination) { + this.#linkPins() + } } } @@ -144,6 +163,9 @@ export default class LinkElement extends IElement { const nodeElement = this.#destination.getNodeElement() nodeElement.removeEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler) nodeElement.removeEventListener(Configuration.nodeDragLocalEventName, this.#nodeDragDestinatonHandler) + if (this.#source) { + this.#unlinkPins() + } } this.#destination = pin if (this.#destination) { @@ -151,6 +173,9 @@ export default class LinkElement extends IElement { nodeElement.addEventListener(Configuration.nodeDeleteEventName, this.#nodeDeleteHandler) nodeElement.addEventListener(Configuration.nodeDragLocalEventName, this.#nodeDragDestinatonHandler) this.setDestinationLocation() + if (this.#source) { + this.#linkPins() + } } } diff --git a/js/element/NodeElement.js b/js/element/NodeElement.js index abdd822..45b7ea2 100644 --- a/js/element/NodeElement.js +++ b/js/element/NodeElement.js @@ -30,6 +30,10 @@ export default class NodeElement extends ISelectableDraggableElement { this.dispatchDeleteEvent() } + getNodeName() { + return this.entity.getName() + } + /** * @returns {PinEntity[]} */ diff --git a/js/element/PinElement.js b/js/element/PinElement.js index 74faaf3..b8d60dc 100644 --- a/js/element/PinElement.js +++ b/js/element/PinElement.js @@ -2,10 +2,16 @@ import IElement from "./IElement" import MouseCreateLink from "../input/mouse/MouseCreateLink" import PinTemplate from "../template/PinTemplate" +/** + * @typedef {import("./NodeElement").default} NodeElement + */ export default class PinElement extends IElement { static tagName = "ueb-pin" + /** @type {NodeElement} */ + nodeElement + /** @type {HTMLElement} */ clickableElement @@ -37,10 +43,17 @@ export default class PinElement extends IElement { /** * @returns {String} */ - getPinDisplayName() { + getPinName() { return this.entity.PinName } + /** + * @returns {String} + */ + getPinDisplayName() { + return this.entity.PinFriendlyName + } + isInput() { return this.entity.isInput() } @@ -76,6 +89,20 @@ export default class PinElement extends IElement { getNodeElement() { return this.closest("ueb-node") } + + /** + * @param {PinElement} targetPinElement + */ + linkTo(targetPinElement) { + this.entity.linkTo(targetPinElement.nodeElement.getNodeName(), targetPinElement.entity) + } + + /** + * @param {PinElement} targetPinElement + */ + unlinkFrom(targetPinElement) { + this.entity.unlinkFrom(targetPinElement.nodeElement.getNodeName(), targetPinElement.entity) + } } customElements.define(PinElement.tagName, PinElement) diff --git a/js/entity/ObjectEntity.js b/js/entity/ObjectEntity.js index 19c7aa7..cd54c29 100755 --- a/js/entity/ObjectEntity.js +++ b/js/entity/ObjectEntity.js @@ -28,7 +28,7 @@ export default class ObjectEntity extends IEntity { /** * @returns {String} The name of the node */ - getNodeDisplayName() { + getName() { return this.Name } } diff --git a/js/entity/PinEntity.js b/js/entity/PinEntity.js index f05f352..539c671 100755 --- a/js/entity/PinEntity.js +++ b/js/entity/PinEntity.js @@ -65,17 +65,49 @@ export default class PinEntity extends IEntity { } /** - * @param {PinReferenceEntity} pinReferenceEntity + * @param {String} targetObjectName + * @param {PinEntity} targetPinEntity */ - connectTo(pinReferenceEntity) { + linkTo(targetObjectName, targetPinEntity) { /** @type {PinReferenceEntity[]} */ this.LinkedTo - this.LinkedTo.forEach(reference => { + const pinExists = !this.LinkedTo.find( + /** @type {PinReferenceEntity} */ + pinReferenceEntity => { + return pinReferenceEntity.objectName == targetObjectName + && pinReferenceEntity.pinGuid == targetPinEntity.PinId + }) + if (pinExists) { + this.LinkedTo.push(new PinReferenceEntity({ + objectName: targetObjectName, + pinGuid: targetPinEntity.PinId + })) + return true + } + return false + } - }) + /** + * @param {String} targetObjectName + * @param {PinEntity} targetPinEntity + */ + unlinkFrom(targetObjectName, targetPinEntity) { + /** @type {PinReferenceEntity[]} */ + this.LinkedTo + const indexElement = this.LinkedTo.findIndex( + /** @type {PinReferenceEntity} */ + pinReferenceEntity => { + return pinReferenceEntity.objectName == targetObjectName + && pinReferenceEntity.pinGuid == targetPinEntity.PinId + }) + if (indexElement >= 0) { + this.LinkedTo.splice(indexElement, 1) + return true + } + return false } getType() { - return this.PinType.PinCategory ?? "object" + return this.PinType.PinCategory } } diff --git a/js/template/LinkTemplate.js b/js/template/LinkTemplate.js index 12d2628..88812c9 100755 --- a/js/template/LinkTemplate.js +++ b/js/template/LinkTemplate.js @@ -25,7 +25,7 @@ export default class LinkTemplate extends ITemplate { return x => a / x + q } - /* + /** * Returns a function performing a clamped line passing through two points. It is clamped after and before the * points. It is easier explained with an example. * b ______ @@ -55,7 +55,7 @@ export default class LinkTemplate extends ITemplate { static c2DecreasingValue = LinkTemplate.decreasingValue(-0.06, [500, 130]) - static c1Clamped = LinkTemplate.clampedLine([0, 100], [100, 30]) + static c2Clamped = LinkTemplate.clampedLine([0, 100], [200, 30]) /** * Computes the html content of the target element. @@ -150,11 +150,8 @@ export default class LinkTemplate extends ITemplate { : 10 ) * fillRatio - let c2 = LinkTemplate.clampedLine([0, 100], [100, 30])(xInverted ? -dx : dx) + start - c2 = Math.min( - c2, - LinkTemplate.c2DecreasingValue(width) - ) + let c2 = LinkTemplate.c2Clamped(xInverted ? -dx : dx) + start + c2 = Math.min(c2, LinkTemplate.c2DecreasingValue(width)) const d = Configuration.linkRightSVGPath(start, c1, c2) // TODO move to CSS when Firefox will support property d and css will have enough functions link.pathElement.setAttribute("d", d) diff --git a/js/template/NodeTemplate.js b/js/template/NodeTemplate.js index 6db79b2..9c2d719 100755 --- a/js/template/NodeTemplate.js +++ b/js/template/NodeTemplate.js @@ -20,7 +20,7 @@ export default class NodeTemplate extends SelectableDraggableTemplate {
- ${sanitizeText(node.entity.getNodeDisplayName())} + ${sanitizeText(node.entity.getName())}
diff --git a/js/template/PinTemplate.js b/js/template/PinTemplate.js index 8c10517..6c0b427 100755 --- a/js/template/PinTemplate.js +++ b/js/template/PinTemplate.js @@ -4,6 +4,7 @@ import sanitizeText from "./sanitizeText" import Utility from "../Utility" /** + * @typedef {import("../element/NodeElement").default} NodeElement * @typedef {import("../element/PinElement").default} PinElement */ export default class PinTemplate extends ITemplate { @@ -39,6 +40,10 @@ export default class PinTemplate extends ITemplate { pin.isConnected() ? "ueb-pin-fill" : null ) pin.clickableElement = pin + pin.nodeElement = pin.closest("ueb-node") + if (!pin.nodeElement) { + window.customElements.whenDefined(linkMessage.constructor.tagName).then(linkMessage) + } } /**