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 {
@@ -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 {
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)
+ }
}
/**