diff --git a/dist/css/ueblueprint-node-value-type-color.css b/dist/css/ueblueprint-node-value-type-color.css
old mode 100644
new mode 100755
diff --git a/dist/css/ueblueprint-node-value-type-color.css.map b/dist/css/ueblueprint-node-value-type-color.css.map
old mode 100644
new mode 100755
diff --git a/dist/css/ueblueprint-style.css b/dist/css/ueblueprint-style.css
old mode 100644
new mode 100755
diff --git a/dist/css/ueblueprint-style.css.map b/dist/css/ueblueprint-style.css.map
old mode 100644
new mode 100755
diff --git a/dist/font/roboto-bold.woff b/dist/font/roboto-bold.woff
old mode 100644
new mode 100755
diff --git a/dist/font/roboto-bold.woff2 b/dist/font/roboto-bold.woff2
old mode 100644
new mode 100755
diff --git a/dist/font/roboto-light.woff b/dist/font/roboto-light.woff
old mode 100644
new mode 100755
diff --git a/dist/font/roboto-light.woff2 b/dist/font/roboto-light.woff2
old mode 100644
new mode 100755
diff --git a/dist/font/roboto-regular.woff b/dist/font/roboto-regular.woff
old mode 100644
new mode 100755
diff --git a/dist/font/roboto-regular.woff2 b/dist/font/roboto-regular.woff2
old mode 100644
new mode 100755
diff --git a/dist/ueblueprint.js b/dist/ueblueprint.js
old mode 100644
new mode 100755
index d0781fa..7e49c7b
--- a/dist/ueblueprint.js
+++ b/dist/ueblueprint.js
@@ -302,20 +302,30 @@ class FastSelectionModel {
}
+/**
+ * @typedef {import("../Blueprint").default} Blueprint
+ * @typedef {import("../entity/Entity").default} Entity
+ * @typedef {import("../input/Context").default} Context
+ * @typedef {import("../template/Template").default} Template
+ */
+
class GraphElement extends HTMLElement {
/**
*
- * @param {import("../template/Template").default} template The template to render this node
+ * @param {Entity} entity The entity containing blueprint related data for this graph element
+ * @param {Template} template The template to render this node
*/
constructor(entity, template) {
super();
- /** @type {import("../Blueprint").default}" */
+ /** @type {Blueprint}" */
this.blueprint = null;
- /** @type {import("../entity/Entity").default}" */
+ /** @type {Entity}" */
this.entity = entity;
- /** @type {import("../template/Template").default}" */
+ /** @type {Template}" */
this.template = template;
+ /** @type {Context[]} */
+ this.inputObjects = [];
}
getTemplate() {
@@ -325,9 +335,15 @@ class GraphElement extends HTMLElement {
connectedCallback() {
this.blueprint = this.closest("ueb-blueprint");
this.template.apply(this);
+ this.inputObjects = this.createInputObjects();
}
disconnectedCallback() {
+ this.inputObjects.forEach(v => v.unlistenDOMElement());
+ }
+
+ createInputObjects() {
+ return []
}
}
@@ -569,6 +585,14 @@ class BlueprintTemplate extends Template {
}
}
+class Configuration {
+
+ static deleteNodesKeyboardKey = "Delete"
+ static expandGridSize = 400
+ static gridSize = 16
+ static gridSnap = 16
+}
+
class Context {
constructor(target, blueprint, options) {
@@ -577,19 +601,19 @@ class Context {
/** @type {import("../Blueprint").default}" */
this.blueprint = blueprint;
this.options = options;
+ let self = this;
+ this.blueprintFocusHandler = _ => self.blueprintFocused();
+ this.blueprintUnfocusHandler = _ => self.blueprintUnfocused();
if (options?.wantsFocusCallback ?? false) {
- let self = this;
- this.blueprintfocusHandler = _ => self.blueprintFocused();
- this.blueprintunfocusHandler = _ => self.blueprintUnfocused();
- this.blueprint.addEventListener("blueprintfocus", this.blueprintfocusHandler);
- this.blueprint.addEventListener("blueprintunfocus", this.blueprintunfocusHandler);
+ this.blueprint.addEventListener("blueprint-focus", this.blueprintFocusHandler);
+ this.blueprint.addEventListener("blueprint-unfocus", this.blueprintUnfocusHandler);
}
}
unlistenDOMElement() {
this.blueprintUnfocused();
- this.blueprint.removeEventListener("blueprintfocus", this.blueprintfocusHandler);
- this.blueprint.removeEventListener("blueprintunfocus", this.blueprintunfocusHandler);
+ this.blueprint.removeEventListener("blueprint-focus", this.blueprintFocusHandler);
+ this.blueprint.removeEventListener("blueprint-unfocus", this.blueprintUnfocusHandler);
}
@@ -883,6 +907,7 @@ class PinReferenceEntity extends Entity {
class PinEntity$1 extends Entity {
+ static lookbehind = "Pin"
static attributes = {
PinId: GuidEntity,
PinName: "",
@@ -1099,25 +1124,28 @@ class Grammar {
}
}
// Meta grammar
- static CreateAttributeGrammar = (r, attributeGrammar, attributeSupplier, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
- attributeGrammar.skip(valueSeparator)
+ static CreateAttributeGrammar = (r, entityType, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
+ r.AttributeName.skip(valueSeparator)
.chain(attributeName => {
const attributeKey = attributeName.split(".");
- const attribute = attributeSupplier(attributeKey);
+ const attribute = Utility.objectGet(entityType.attributes, attributeKey);
let attributeValueGrammar = Grammar.getGrammarForType(r, attribute, r.AttributeAnyValue);
+ // Returns attributeSetter: a function called with an object as argument that will set the correct attribute value
return attributeValueGrammar.map(attributeValue =>
entity => Utility.objectSet(entity, attributeKey, attributeValue, true)
- ) // returns attributeSetter: a function called with an object as argument that will set the correct attribute value
+ )
})
// Meta grammar
- static CreateMultiAttributeGrammar = (r, keyGrammar, entityType, attributeSupplier) =>
+ static CreateMultiAttributeGrammar = (r, entityType) =>
/**
* Basically this creates a parser that looks for a string like 'Key (A=False,B="Something",)'
* Then it populates an object of type EntityType with the attribute values found inside the parentheses.
*/
P.seqMap(
- P.seq(keyGrammar, P.optWhitespace, P.string("(")),
- Grammar.CreateAttributeGrammar(r, r.AttributeName, attributeSupplier)
+ entityType.lookbehind
+ ? P.seq(P.string(entityType.lookbehind), P.optWhitespace, P.string("("))
+ : P.string("("),
+ Grammar.CreateAttributeGrammar(r, entityType)
.trim(P.optWhitespace)
.sepBy(P.string(","))
.skip(P.regex(/,?/).then(P.optWhitespace)), // Optional trailing comma
@@ -1127,18 +1155,8 @@ class Grammar {
attributes.forEach(attributeSetter => attributeSetter(result));
return result
})
- FunctionReference = r => Grammar.CreateMultiAttributeGrammar(
- r,
- P.succeed(),
- FunctionReferenceEntity,
- attributeKey => Utility.objectGet(FunctionReferenceEntity.attributes, attributeKey)
- )
- Pin = r => Grammar.CreateMultiAttributeGrammar(
- r,
- P.string("Pin"),
- PinEntity$1,
- attributeKey => Utility.objectGet(PinEntity$1.attributes, attributeKey)
- )
+ FunctionReference = r => Grammar.CreateMultiAttributeGrammar(r, FunctionReferenceEntity)
+ Pin = r => Grammar.CreateMultiAttributeGrammar(r, PinEntity$1)
CustomProperties = r =>
P.string("CustomProperties")
.then(P.whitespace)
@@ -1155,7 +1173,7 @@ class Grammar {
P
.alt(
r.CustomProperties,
- Grammar.CreateAttributeGrammar(r, r.AttributeName, attributeKey => Utility.objectGet(ObjectEntity.attributes, attributeKey))
+ Grammar.CreateAttributeGrammar(r, ObjectEntity)
)
.sepBy1(P.whitespace),
P.seq(r.WhitespaceNewline, P.string("End"), P.whitespace, P.string("Object")),
@@ -1317,15 +1335,15 @@ class Copy extends Context {
super(target, blueprint, options);
this.serializer = new ObjectSerializer();
let self = this;
- this.copyHandle = _ => self.copied();
+ this.copyHandler = _ => self.copied();
}
blueprintFocused() {
- document.body.addEventListener("copy", this.copyHandle);
+ document.body.addEventListener("copy", this.copyHandler);
}
blueprintUnfocused() {
- document.body.removeEventListener("copy", this.copyHandle);
+ document.body.removeEventListener("copy", this.copyHandler);
}
copied() {
@@ -1476,99 +1494,50 @@ class DragScroll extends MouseClickDrag {
}
}
-class KeyboardShortcut extends Context {
+/**
+ * @typedef {import("../graph/GraphLink").default} GraphLink
+ */
+class LinkTemplate extends Template {
- constructor(target, blueprint, options = {}) {
- options.wantsFocusCallback = true;
- super(target, blueprint, options);
-
- /** @type {String[]} */
- this.key = this.options.key;
- this.ctrlKey = options.ctrlKey ?? false;
- this.shiftKey = options.shiftKey ?? false;
- this.altKey = options.altKey ?? false;
- this.metaKey = options.metaKey ?? false;
-
- let self = this;
- this.keyDownHandler = e => {
- if (
- e.code == self.key
- && e.ctrlKey === self.ctrlKey
- && e.shiftKey === self.shiftKey
- && e.altKey === self.altKey
- && e.metaKey === self.metaKey
- ) {
- self.fire();
- }
- };
+ /**
+ * Computes the html content of the target element.
+ * @param {GraphLink} link Link connecting two graph nodes
+ * @returns The result html
+ */
+ render(link) {
+ return html`
+
+ `
}
/**
- *
- * @param {String} keyString
- * @returns {Object}
+ * Applies the style to the element.
+ * @param {GraphLink} link Element of the graph
*/
- static keyOptionsParse(options, keyString) {
- options.key = keyString;
- return options
- }
+ apply(link) {
+ super.apply(link);
- blueprintFocused() {
- document.addEventListener("keydown", this.keyDownHandler);
}
- blueprintUnfocused() {
- document.removeEventListener("keydown", this.keyDownHandler);
- }
-
- fire() {
- }
-}
-
-class Configuration {
-
- static deleteNodesKeyboardKey = "Delete"
- static expandGridSize = 400
- static gridSize = 16
- static gridSnap = 16
-}
-
-class KeyvoardCanc extends KeyboardShortcut {
-
/**
- *
- * @param {HTMLElement} target
- * @param {import("../Blueprint").default} blueprint
- * @param {OBject} options
+ * Applies the style relative to the source pin location.
+ * @param {GraphLink} link Link element
*/
- constructor(target, blueprint, options = {}) {
- options = KeyboardShortcut.keyOptionsParse(options, Configuration.deleteNodesKeyboardKey);
- super(target, blueprint, options);
+ applySourceLocation(link, initialPosition) {
+ // Set initial position
+ link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]));
+ link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]));
}
- fire() {
- this.blueprint.removeGraphElement(...this.blueprint.getNodes(true));
- }
-}
-
-class MouseTracking extends Pointing {
-
- constructor(target, blueprint, options = {}) {
- options.wantsFocusCallback = true;
- super(target, blueprint, options);
-
- let self = this;
- this.mousemoveHandler = e => {
- self.blueprint.entity.mousePosition = self.getLocation(e);
- };
- }
-
- blueprintFocused() {
- this.target.addEventListener("mousemove", this.mousemoveHandler);
- }
-
- blueprintUnfocused() {
- this.target.removeEventListener("mousemove", this.mousemoveHandler);
+ /**
+ * Applies the style relative to the destination pin location.
+ * @param {GraphLink} link Link element
+ */
+ applyDestinationLocation(link, finalPosition) {
+ link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]));
+ link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]));
}
}
@@ -1631,112 +1600,6 @@ class DragLink extends MouseClickDrag {
}
}
-/**
- * @typedef {import("../graph/GraphLink").default} GraphLink
- */
-class LinkTemplate extends Template {
-
- /**
- * Computes the html content of the target element.
- * @param {GraphLink} link Link connecting two graph nodes
- * @returns The result html
- */
- render(link) {
- return html`
-
- `
- }
-
- /**
- * Applies the style to the element.
- * @param {GraphLink} link Element of the graph
- */
- apply(link) {
- super.apply(link);
-
- }
-
- /**
- * Applies the style relative to the source pin location.
- * @param {GraphLink} link Link element
- */
- applySourceLocation(link, initialPosition) {
- // Set initial position
- link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]));
- link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]));
- }
-
- /**
- * Applies the style relative to the destination pin location.
- * @param {GraphLink} link Link element
- */
- applyDestinationLocation(link, finalPosition) {
- link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]));
- link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]));
- }
-}
-
-/**
- * @type {import("./GraphPin").default} GraphPin
- */
-class GraphLink extends GraphElement {
-
- /** @type {GraphPin} */
- #source
- /** @type {GraphPin} */
- #destination
- #nodeDeleteHandler = _ => this.blueprint.removeGraphElement(this)
- #nodeDragSourceHandler = _ => this.setSourceLocation(this.#source.getLinkLocation())
- #nodeDragDestinatonHandler = _ => this.setDestinationLocation(this.#destination.getLinkLocation())
-
- /**
- * @param {?GraphPin} source
- * @param {?GraphPin} destination
- */
- constructor(source, destination) {
- super(this, new LinkTemplate());
- /** @type {import("../template/LinkTemplate").default} */
- this.template;
- this.setSource(source);
- this.setDestination(destination);
- }
-
- setSourceLocation(location) {
- this.template.applySourceLocation(this.#source.getLinkLocation());
- }
-
- setDestinationLocation(location) {
- this.template.applyDestinationLocation(this.#destination.getLinkLocation());
- }
-
- /**
- * @param {GraphPin} graphPin
- */
- setSourcePin(graphPin) {
- this.#source?.removeEventListener("ueb-node-delete", this.#nodeDeleteHandler);
- this.#source?.removeEventListener("ueb-node-drag", this.#nodeDragSourceHandler);
- this.#source = graphPin;
- this.#source?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler);
- this.#source?.addEventListener("ueb-node-drag", this.#nodeDragSourceHandler);
- }
-
- /**
- *
- * @param {GraphPin} graphPin
- */
- setDestinationPin(graphPin) {
- this.#destination?.removeEventListener("ueb-node-delete", this.#nodeDeleteHandler);
- this.#destination?.removeEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler);
- this.#destination = graphPin;
- this.#destination?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler);
- this.#destination?.addEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler);
- }
-}
-
-customElements.define("ueb-link", GraphLink);
-
class GraphPin extends GraphElement {
constructor(entity) {
@@ -1747,11 +1610,12 @@ class GraphPin extends GraphElement {
this.clickableElement = null;
}
- connectedCallback() {
- super.connectedCallback();
- new DragLink(this.clickableElement, this.blueprint, {
- moveEverywhere: true
- });
+ createInputObjects() {
+ return [
+ new DragLink(this.clickableElement, this.blueprint, {
+ moveEverywhere: true
+ }),
+ ]
}
/**
@@ -1802,6 +1666,65 @@ class GraphPin extends GraphElement {
customElements.define("ueb-pin", GraphPin);
+/**
+ * @type {import("./GraphPin").default} GraphPin
+ */
+class GraphLink extends GraphElement {
+
+ /** @type {GraphPin} */
+ #source
+ /** @type {GraphPin} */
+ #destination
+ #nodeDeleteHandler = _ => this.blueprint.removeGraphElement(this)
+ #nodeDragSourceHandler = _ => this.setSourceLocation(this.#source.getLinkLocation())
+ #nodeDragDestinatonHandler = _ => this.setDestinationLocation(this.#destination.getLinkLocation())
+
+ /**
+ * @param {?GraphPin} source
+ * @param {?GraphPin} destination
+ */
+ constructor(source, destination) {
+ super(this, new LinkTemplate());
+ /** @type {import("../template/LinkTemplate").default} */
+ this.template;
+ this.setSource(source);
+ this.setDestination(destination);
+ }
+
+ setSourceLocation(location) {
+ this.template.applySourceLocation(this.#source.getLinkLocation());
+ }
+
+ setDestinationLocation(location) {
+ this.template.applyDestinationLocation(this.#destination.getLinkLocation());
+ }
+
+ /**
+ * @param {GraphPin} graphPin
+ */
+ setSourcePin(graphPin) {
+ this.#source?.removeEventListener("ueb-node-delete", this.#nodeDeleteHandler);
+ this.#source?.removeEventListener("ueb-node-drag", this.#nodeDragSourceHandler);
+ this.#source = graphPin;
+ this.#source?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler);
+ this.#source?.addEventListener("ueb-node-drag", this.#nodeDragSourceHandler);
+ }
+
+ /**
+ *
+ * @param {GraphPin} graphPin
+ */
+ setDestinationPin(graphPin) {
+ this.#destination?.removeEventListener("ueb-node-delete", this.#nodeDeleteHandler);
+ this.#destination?.removeEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler);
+ this.#destination = graphPin;
+ this.#destination?.addEventListener("ueb-node-delete", this.#nodeDeleteHandler);
+ this.#destination?.addEventListener("ueb-node-drag", this.#nodeDragDestinatonHandler);
+ }
+}
+
+customElements.define("ueb-link", GraphLink);
+
/**
* @typedef {import("../graph/SelectableDraggable").default} SelectableDraggable
*/
@@ -1956,16 +1879,12 @@ class SelectableDraggable extends GraphElement {
};
}
- connectedCallback() {
- super.connectedCallback();
- this.dragObject = new DragMove(this, this.blueprint, {
- looseTarget: true
- });
- }
-
- disconnectedCallback() {
- super.disconnectedCallback();
- this.dragObject.unlistenDOMElement();
+ createInputObjects() {
+ return [
+ new DragMove(this, this.blueprint, {
+ looseTarget: true
+ }),
+ ]
}
setLocation(value = [0, 0]) {
@@ -2025,10 +1944,6 @@ class GraphNode extends SelectableDraggable {
return new GraphNode(entity)
}
- connectedCallback() {
- super.connectedCallback();
- }
-
disconnectedCallback() {
super.disconnectedCallback();
this.dispatchDeleteEvent();
@@ -2065,6 +1980,94 @@ class GraphNode extends SelectableDraggable {
customElements.define("ueb-node", GraphNode);
+class KeyboardShortcut extends Context {
+
+ constructor(target, blueprint, options = {}) {
+ options.wantsFocusCallback = true;
+ super(target, blueprint, options);
+
+ /** @type {String[]} */
+ this.key = this.options.key;
+ this.ctrlKey = options.ctrlKey ?? false;
+ this.shiftKey = options.shiftKey ?? false;
+ this.altKey = options.altKey ?? false;
+ this.metaKey = options.metaKey ?? false;
+
+ let self = this;
+ this.keyDownHandler = e => {
+ if (
+ e.code == self.key
+ && e.ctrlKey === self.ctrlKey
+ && e.shiftKey === self.shiftKey
+ && e.altKey === self.altKey
+ && e.metaKey === self.metaKey
+ ) {
+ self.fire();
+ }
+ };
+ }
+
+ /**
+ *
+ * @param {String} keyString
+ * @returns {Object}
+ */
+ static keyOptionsParse(options, keyString) {
+ options.key = keyString;
+ return options
+ }
+
+ blueprintFocused() {
+ document.addEventListener("keydown", this.keyDownHandler);
+ }
+
+ blueprintUnfocused() {
+ document.removeEventListener("keydown", this.keyDownHandler);
+ }
+
+ fire() {
+ }
+}
+
+class KeyvoardCanc extends KeyboardShortcut {
+
+ /**
+ *
+ * @param {HTMLElement} target
+ * @param {import("../Blueprint").default} blueprint
+ * @param {OBject} options
+ */
+ constructor(target, blueprint, options = {}) {
+ options = KeyboardShortcut.keyOptionsParse(options, Configuration.deleteNodesKeyboardKey);
+ super(target, blueprint, options);
+ }
+
+ fire() {
+ this.blueprint.removeGraphElement(...this.blueprint.getNodes(true));
+ }
+}
+
+class MouseTracking extends Pointing {
+
+ constructor(target, blueprint, options = {}) {
+ options.wantsFocusCallback = true;
+ super(target, blueprint, options);
+
+ let self = this;
+ this.mousemoveHandler = e => {
+ self.blueprint.entity.mousePosition = self.getLocation(e);
+ };
+ }
+
+ blueprintFocused() {
+ this.target.addEventListener("mousemove", this.mousemoveHandler);
+ }
+
+ blueprintUnfocused() {
+ this.target.removeEventListener("mousemove", this.mousemoveHandler);
+ }
+}
+
class Paste extends Context {
constructor(target, blueprint, options = {}) {
@@ -2299,30 +2302,28 @@ class Blueprint extends GraphElement {
this.template.applyTranlate(this);
}
- connectedCallback() {
- super.connectedCallback();
-
- this.copyObject = new Copy(this.getGridDOMElement(), this);
- this.pasteObject = new Paste(this.getGridDOMElement(), this);
- this.cancObject = new KeyvoardCanc(this.getGridDOMElement(), this);
-
- this.zoomObject = new Zoom(this.getGridDOMElement(), this, {
- looseTarget: true,
- });
- this.selectObject = new Select(this.getGridDOMElement(), this, {
- clickButton: 0,
- exitAnyButton: true,
- moveEverywhere: true,
- });
- this.dragObject = new DragScroll(this.getGridDOMElement(), this, {
- clickButton: 2,
- exitAnyButton: false,
- looseTarget: true,
- moveEverywhere: true,
- });
-
- this.unfocusObject = new Unfocus(this.getGridDOMElement(), this);
- this.mouseTrackingObject = new MouseTracking(this.getGridDOMElement(), this);
+ createInputObjects() {
+ return [
+ new Copy(this.getGridDOMElement(), this),
+ new Paste(this.getGridDOMElement(), this),
+ new KeyvoardCanc(this.getGridDOMElement(), this),
+ new Zoom(this.getGridDOMElement(), this, {
+ looseTarget: true,
+ }),
+ new Select(this.getGridDOMElement(), this, {
+ clickButton: 0,
+ exitAnyButton: true,
+ moveEverywhere: true,
+ }),
+ new DragScroll(this.getGridDOMElement(), this, {
+ clickButton: 2,
+ exitAnyButton: false,
+ looseTarget: true,
+ moveEverywhere: true,
+ }),
+ new Unfocus(this.getGridDOMElement(), this),
+ new MouseTracking(this.getGridDOMElement(), this),
+ ]
}
getGridDOMElement() {
@@ -2332,9 +2333,6 @@ class Blueprint extends GraphElement {
disconnectedCallback() {
super.disconnectedCallback();
setSelected(false);
- this.dragObject.unlistenDOMElement();
- this.selectObject.unlistenDOMElement();
- this.pasteObject.unlistenDOMElement();
}
getScroll() {
@@ -2570,7 +2568,7 @@ class Blueprint extends GraphElement {
if (this.focused == value) {
return;
}
- let event = new CustomEvent(value ? "blueprintfocus" : "blueprintunfocus");
+ let event = new CustomEvent(value ? "blueprint-focus" : "blueprint-unfocus");
this.focused = value;
this.dataset.focused = this.focused;
if (!this.focused) {
diff --git a/font/roboto-bold.woff b/font/roboto-bold.woff
old mode 100644
new mode 100755
diff --git a/font/roboto-bold.woff2 b/font/roboto-bold.woff2
old mode 100644
new mode 100755
diff --git a/font/roboto-light.woff b/font/roboto-light.woff
old mode 100644
new mode 100755
diff --git a/font/roboto-light.woff2 b/font/roboto-light.woff2
old mode 100644
new mode 100755
diff --git a/font/roboto-regular.woff b/font/roboto-regular.woff
old mode 100644
new mode 100755
diff --git a/font/roboto-regular.woff2 b/font/roboto-regular.woff2
old mode 100644
new mode 100755
diff --git a/js/Blueprint.js b/js/Blueprint.js
index d937759..01e508a 100755
--- a/js/Blueprint.js
+++ b/js/Blueprint.js
@@ -1,7 +1,10 @@
import BlueprintTemplate from "./template/BlueprintTemplate"
+import Configuration from "./Configuration"
import Copy from "./input/Copy"
import DragScroll from "./input/DragScroll"
import GraphElement from "./graph/GraphElement"
+import GraphLink from "./graph/GraphLink"
+import GraphNode from "./graph/GraphNode"
import GraphSelector from "./graph/GraphSelector"
import KeyboardCanc from "./input/KeyboardCanc"
import MouseTracking from "./input/MouseTracking"
@@ -10,9 +13,6 @@ import Select from "./input/Select"
import Unfocus from "./input/Unfocus"
import Utility from "./Utility"
import Zoom from "./input/Zoom"
-import GraphNode from "./graph/GraphNode"
-import GraphLink from "./graph/GraphLink"
-import Configuration from "./Configuration"
export default class Blueprint extends GraphElement {
@@ -93,30 +93,28 @@ export default class Blueprint extends GraphElement {
this.template.applyTranlate(this)
}
- connectedCallback() {
- super.connectedCallback()
-
- this.copyObject = new Copy(this.getGridDOMElement(), this)
- this.pasteObject = new Paste(this.getGridDOMElement(), this)
- this.cancObject = new KeyboardCanc(this.getGridDOMElement(), this)
-
- this.zoomObject = new Zoom(this.getGridDOMElement(), this, {
- looseTarget: true,
- })
- this.selectObject = new Select(this.getGridDOMElement(), this, {
- clickButton: 0,
- exitAnyButton: true,
- moveEverywhere: true,
- })
- this.dragObject = new DragScroll(this.getGridDOMElement(), this, {
- clickButton: 2,
- exitAnyButton: false,
- looseTarget: true,
- moveEverywhere: true,
- })
-
- this.unfocusObject = new Unfocus(this.getGridDOMElement(), this)
- this.mouseTrackingObject = new MouseTracking(this.getGridDOMElement(), this)
+ createInputObjects() {
+ return [
+ new Copy(this.getGridDOMElement(), this),
+ new Paste(this.getGridDOMElement(), this),
+ new KeyboardCanc(this.getGridDOMElement(), this),
+ new Zoom(this.getGridDOMElement(), this, {
+ looseTarget: true,
+ }),
+ new Select(this.getGridDOMElement(), this, {
+ clickButton: 0,
+ exitAnyButton: true,
+ moveEverywhere: true,
+ }),
+ new DragScroll(this.getGridDOMElement(), this, {
+ clickButton: 2,
+ exitAnyButton: false,
+ looseTarget: true,
+ moveEverywhere: true,
+ }),
+ new Unfocus(this.getGridDOMElement(), this),
+ new MouseTracking(this.getGridDOMElement(), this),
+ ]
}
getGridDOMElement() {
@@ -126,9 +124,6 @@ export default class Blueprint extends GraphElement {
disconnectedCallback() {
super.disconnectedCallback()
setSelected(false)
- this.dragObject.unlistenDOMElement()
- this.selectObject.unlistenDOMElement()
- this.pasteObject.unlistenDOMElement()
}
getScroll() {
@@ -364,7 +359,7 @@ export default class Blueprint extends GraphElement {
if (this.focused == value) {
return;
}
- let event = new CustomEvent(value ? "blueprintfocus" : "blueprintunfocus")
+ let event = new CustomEvent(value ? "blueprint-focus" : "blueprint-unfocus")
this.focused = value
this.dataset.focused = this.focused
if (!this.focused) {
diff --git a/js/Configuration.js b/js/Configuration.js
old mode 100644
new mode 100755
index d5153aa..b5c8138
--- a/js/Configuration.js
+++ b/js/Configuration.js
@@ -1,7 +1,7 @@
-export default class Configuration {
-
- static deleteNodesKeyboardKey = "Delete"
- static expandGridSize = 400
- static gridSize = 16
- static gridSnap = 16
-}
+export default class Configuration {
+
+ static deleteNodesKeyboardKey = "Delete"
+ static expandGridSize = 400
+ static gridSize = 16
+ static gridSnap = 16
+}
diff --git a/js/action/Actions.js b/js/action/Actions.js
old mode 100644
new mode 100755
index b444f1f..8b35a67
--- a/js/action/Actions.js
+++ b/js/action/Actions.js
@@ -1,8 +1,8 @@
-export default class Action {
-
- apply() {
- }
-
- revert() {
- }
+export default class Action {
+
+ apply() {
+ }
+
+ revert() {
+ }
}
\ No newline at end of file
diff --git a/js/entity/KeyBinding.js b/js/entity/KeyBinding.js
new file mode 100755
index 0000000..b3e8005
--- /dev/null
+++ b/js/entity/KeyBinding.js
@@ -0,0 +1,16 @@
+import Entity from "./Entity"
+
+export default class KeyBinding extends Entity {
+
+ static attributes = {
+ bCtrlDown: false,
+ bAltDown: false,
+ bShiftDown: false,
+ Key: String,
+ CommandName: String,
+ }
+
+ getAttributes() {
+ return KeyBinding.attributes
+ }
+}
diff --git a/js/entity/PathSymbolEntity.js b/js/entity/PathSymbolEntity.js
old mode 100644
new mode 100755
index 6db4172..aff0238
--- a/js/entity/PathSymbolEntity.js
+++ b/js/entity/PathSymbolEntity.js
@@ -1,16 +1,16 @@
-import Entity from "./Entity"
-
-export default class PathSymbolEntity extends Entity {
-
- static attributes = {
- value: String
- }
-
- getAttributes() {
- return PathSymbolEntity.attributes
- }
-
- toString() {
- return this.value
- }
-}
+import Entity from "./Entity"
+
+export default class PathSymbolEntity extends Entity {
+
+ static attributes = {
+ value: String
+ }
+
+ getAttributes() {
+ return PathSymbolEntity.attributes
+ }
+
+ toString() {
+ return this.value
+ }
+}
diff --git a/js/entity/PinEntity.js b/js/entity/PinEntity.js
index c0a75bb..78a1318 100755
--- a/js/entity/PinEntity.js
+++ b/js/entity/PinEntity.js
@@ -7,6 +7,7 @@ import TypeInitialization from "./TypeInitialization"
export default class PinEntity extends Entity {
+ static lookbehind = "Pin"
static attributes = {
PinId: GuidEntity,
PinName: "",
diff --git a/js/graph/GraphElement.js b/js/graph/GraphElement.js
index e86e801..c510686 100755
--- a/js/graph/GraphElement.js
+++ b/js/graph/GraphElement.js
@@ -1,17 +1,27 @@
+/**
+ * @typedef {import("../Blueprint").default} Blueprint
+ * @typedef {import("../entity/Entity").default} Entity
+ * @typedef {import("../input/Context").default} Context
+ * @typedef {import("../template/Template").default} Template
+ */
+
export default class GraphElement extends HTMLElement {
/**
*
- * @param {import("../template/Template").default} template The template to render this node
+ * @param {Entity} entity The entity containing blueprint related data for this graph element
+ * @param {Template} template The template to render this node
*/
constructor(entity, template) {
super()
- /** @type {import("../Blueprint").default}" */
+ /** @type {Blueprint}" */
this.blueprint = null
- /** @type {import("../entity/Entity").default}" */
+ /** @type {Entity}" */
this.entity = entity
- /** @type {import("../template/Template").default}" */
+ /** @type {Template}" */
this.template = template
+ /** @type {Context[]} */
+ this.inputObjects = []
}
getTemplate() {
@@ -21,8 +31,14 @@ export default class GraphElement extends HTMLElement {
connectedCallback() {
this.blueprint = this.closest("ueb-blueprint")
this.template.apply(this)
+ this.inputObjects = this.createInputObjects()
}
disconnectedCallback() {
+ this.inputObjects.forEach(v => v.unlistenDOMElement())
+ }
+
+ createInputObjects() {
+ return []
}
}
diff --git a/js/graph/GraphLink.js b/js/graph/GraphLink.js
index 3f20d8f..6847112 100755
--- a/js/graph/GraphLink.js
+++ b/js/graph/GraphLink.js
@@ -17,8 +17,8 @@ export default class GraphLink extends GraphElement {
#nodeDragDestinatonHandler = _ => this.setDestinationLocation(this.#destination.getLinkLocation())
/**
- * @param {?GraphPin} source
- * @param {?GraphPin} destination
+ * @param {?GraphPin} source
+ * @param {?GraphPin} destination
*/
constructor(source, destination) {
super(this, new LinkTemplate())
diff --git a/js/graph/GraphNode.js b/js/graph/GraphNode.js
index 0050226..1e0f755 100755
--- a/js/graph/GraphNode.js
+++ b/js/graph/GraphNode.js
@@ -23,10 +23,6 @@ export default class GraphNode extends SelectableDraggable {
return new GraphNode(entity)
}
- connectedCallback() {
- super.connectedCallback()
- }
-
disconnectedCallback() {
super.disconnectedCallback()
this.dispatchDeleteEvent()
diff --git a/js/graph/GraphPin.js b/js/graph/GraphPin.js
old mode 100644
new mode 100755
index 95ca1ba..3e95f3d
--- a/js/graph/GraphPin.js
+++ b/js/graph/GraphPin.js
@@ -1,69 +1,70 @@
-import GraphElement from "./GraphElement"
-import PinTemplate from "../template/PinTemplate"
-import DragLink from "../input/DragLink"
-import GraphLink from "./GraphLink"
-
-export default class GraphPin extends GraphElement {
-
- constructor(entity) {
- super(entity, new PinTemplate())
- /** @type {import("../entity/PinEntity").default} */
- this.entity
- /** @type {HTMLElement} */
- this.clickableElement = null
- }
-
- connectedCallback() {
- super.connectedCallback()
- new DragLink(this.clickableElement, this.blueprint, {
- moveEverywhere: true
- })
- }
-
- /**
- *
- * @returns {String}
- */
- getPinDisplayName() {
- return this.entity.PinName
- }
-
- getAttributes() {
- return PinEntity.attributes
- }
-
- isInput() {
- return this.entity.isInput()
- }
-
- isOutput() {
- return this.entity.isOutput()
- }
-
- isConnected() {
- return this.entity.isConnected()
- }
-
- getType() {
- return this.entity.getType()
- }
-
- /**
- *
- * @returns {GraphLink} The link created
- */
- dragLink() {
- let link = new GraphLink(this)
- return link
- }
-
- /**
- * Returns The exact location where the link originates from or arrives at.
- * @returns {Number[]} The location array
- */
- getLinkLocation() {
- return [0, 0];
- }
-}
-
-customElements.define("ueb-pin", GraphPin)
+import GraphElement from "./GraphElement"
+import PinTemplate from "../template/PinTemplate"
+import DragLink from "../input/DragLink"
+import GraphLink from "./GraphLink"
+
+export default class GraphPin extends GraphElement {
+
+ constructor(entity) {
+ super(entity, new PinTemplate())
+ /** @type {import("../entity/PinEntity").default} */
+ this.entity
+ /** @type {HTMLElement} */
+ this.clickableElement = null
+ }
+
+ createInputObjects() {
+ return [
+ new DragLink(this.clickableElement, this.blueprint, {
+ moveEverywhere: true
+ }),
+ ]
+ }
+
+ /**
+ *
+ * @returns {String}
+ */
+ getPinDisplayName() {
+ return this.entity.PinName
+ }
+
+ getAttributes() {
+ return PinEntity.attributes
+ }
+
+ isInput() {
+ return this.entity.isInput()
+ }
+
+ isOutput() {
+ return this.entity.isOutput()
+ }
+
+ isConnected() {
+ return this.entity.isConnected()
+ }
+
+ getType() {
+ return this.entity.getType()
+ }
+
+ /**
+ *
+ * @returns {GraphLink} The link created
+ */
+ dragLink() {
+ let link = new GraphLink(this)
+ return link
+ }
+
+ /**
+ * Returns The exact location where the link originates from or arrives at.
+ * @returns {Number[]} The location array
+ */
+ getLinkLocation() {
+ return [0, 0];
+ }
+}
+
+customElements.define("ueb-pin", GraphPin)
diff --git a/js/graph/SelectableDraggable.js b/js/graph/SelectableDraggable.js
index 09f8b39..b065a0f 100755
--- a/js/graph/SelectableDraggable.js
+++ b/js/graph/SelectableDraggable.js
@@ -17,16 +17,12 @@ export default class SelectableDraggable extends GraphElement {
}
}
- connectedCallback() {
- super.connectedCallback()
- this.dragObject = new DragMove(this, this.blueprint, {
- looseTarget: true
- })
- }
-
- disconnectedCallback() {
- super.disconnectedCallback()
- this.dragObject.unlistenDOMElement()
+ createInputObjects() {
+ return [
+ new DragMove(this, this.blueprint, {
+ looseTarget: true
+ }),
+ ]
}
setLocation(value = [0, 0]) {
diff --git a/js/input/Context.js b/js/input/Context.js
old mode 100644
new mode 100755
index 974834d..9eceb0e
--- a/js/input/Context.js
+++ b/js/input/Context.js
@@ -1,31 +1,31 @@
-export default class Context {
-
- constructor(target, blueprint, options) {
- /** @type {HTMLElement} */
- this.target = target
- /** @type {import("../Blueprint").default}" */
- this.blueprint = blueprint
- this.options = options
- if (options?.wantsFocusCallback ?? false) {
- let self = this
- this.blueprintfocusHandler = _ => self.blueprintFocused()
- this.blueprintunfocusHandler = _ => self.blueprintUnfocused()
- this.blueprint.addEventListener("blueprintfocus", this.blueprintfocusHandler)
- this.blueprint.addEventListener("blueprintunfocus", this.blueprintunfocusHandler)
- }
- }
-
- unlistenDOMElement() {
- this.blueprintUnfocused()
- this.blueprint.removeEventListener("blueprintfocus", this.blueprintfocusHandler)
- this.blueprint.removeEventListener("blueprintunfocus", this.blueprintunfocusHandler)
- }
-
-
- /* Subclasses will probabily override the following methods */
- blueprintFocused() {
- }
-
- blueprintUnfocused() {
- }
-}
+export default class Context {
+
+ constructor(target, blueprint, options) {
+ /** @type {HTMLElement} */
+ this.target = target
+ /** @type {import("../Blueprint").default}" */
+ this.blueprint = blueprint
+ this.options = options
+ let self = this
+ this.blueprintFocusHandler = _ => self.blueprintFocused()
+ this.blueprintUnfocusHandler = _ => self.blueprintUnfocused()
+ if (options?.wantsFocusCallback ?? false) {
+ this.blueprint.addEventListener("blueprint-focus", this.blueprintFocusHandler)
+ this.blueprint.addEventListener("blueprint-unfocus", this.blueprintUnfocusHandler)
+ }
+ }
+
+ unlistenDOMElement() {
+ this.blueprintUnfocused()
+ this.blueprint.removeEventListener("blueprint-focus", this.blueprintFocusHandler)
+ this.blueprint.removeEventListener("blueprint-unfocus", this.blueprintUnfocusHandler)
+ }
+
+
+ /* Subclasses will probabily override the following methods */
+ blueprintFocused() {
+ }
+
+ blueprintUnfocused() {
+ }
+}
diff --git a/js/input/Copy.js b/js/input/Copy.js
old mode 100644
new mode 100755
index 1a9e5f0..862ff7d
--- a/js/input/Copy.js
+++ b/js/input/Copy.js
@@ -1,26 +1,26 @@
-import Context from "./Context"
-import ObjectSerializer from "../serialization/ObjectSerializer"
-
-export default class Copy extends Context {
-
- constructor(target, blueprint, options = {}) {
- options.wantsFocusCallback = true
- super(target, blueprint, options)
- this.serializer = new ObjectSerializer()
- let self = this
- this.copyHandle = _ => self.copied()
- }
-
- blueprintFocused() {
- document.body.addEventListener("copy", this.copyHandle)
- }
-
- blueprintUnfocused() {
- document.body.removeEventListener("copy", this.copyHandle)
- }
-
- copied() {
- const value = this.blueprint.getNodes(true).map(node => this.serializer.write(node.entity)).join("\n")
- navigator.clipboard.writeText(value)
- }
-}
+import Context from "./Context"
+import ObjectSerializer from "../serialization/ObjectSerializer"
+
+export default class Copy extends Context {
+
+ constructor(target, blueprint, options = {}) {
+ options.wantsFocusCallback = true
+ super(target, blueprint, options)
+ this.serializer = new ObjectSerializer()
+ let self = this
+ this.copyHandler = _ => self.copied()
+ }
+
+ blueprintFocused() {
+ document.body.addEventListener("copy", this.copyHandler)
+ }
+
+ blueprintUnfocused() {
+ document.body.removeEventListener("copy", this.copyHandler)
+ }
+
+ copied() {
+ const value = this.blueprint.getNodes(true).map(node => this.serializer.write(node.entity)).join("\n")
+ navigator.clipboard.writeText(value)
+ }
+}
diff --git a/js/input/KeyboardCanc.js b/js/input/KeyboardCanc.js
old mode 100644
new mode 100755
index 75e01a6..0c90d9d
--- a/js/input/KeyboardCanc.js
+++ b/js/input/KeyboardCanc.js
@@ -1,21 +1,21 @@
-import KeyboardShortcut from "./KeyboardShortcut"
-import Configuration from "../Configuration"
-
-
-export default class KeyvoardCanc extends KeyboardShortcut {
-
- /**
- *
- * @param {HTMLElement} target
- * @param {import("../Blueprint").default} blueprint
- * @param {OBject} options
- */
- constructor(target, blueprint, options = {}) {
- options = KeyboardShortcut.keyOptionsParse(options, Configuration.deleteNodesKeyboardKey)
- super(target, blueprint, options)
- }
-
- fire() {
- this.blueprint.removeGraphElement(...this.blueprint.getNodes(true))
- }
+import KeyboardShortcut from "./KeyboardShortcut"
+import Configuration from "../Configuration"
+
+
+export default class KeyvoardCanc extends KeyboardShortcut {
+
+ /**
+ *
+ * @param {HTMLElement} target
+ * @param {import("../Blueprint").default} blueprint
+ * @param {OBject} options
+ */
+ constructor(target, blueprint, options = {}) {
+ options = KeyboardShortcut.keyOptionsParse(options, Configuration.deleteNodesKeyboardKey)
+ super(target, blueprint, options)
+ }
+
+ fire() {
+ this.blueprint.removeGraphElement(...this.blueprint.getNodes(true))
+ }
}
\ No newline at end of file
diff --git a/js/input/KeyboardShortcut.js b/js/input/KeyboardShortcut.js
old mode 100644
new mode 100755
index 8509e74..f621cff
--- a/js/input/KeyboardShortcut.js
+++ b/js/input/KeyboardShortcut.js
@@ -1,50 +1,50 @@
-import Context from "./Context"
-
-export default class KeyboardShortcut extends Context {
-
- constructor(target, blueprint, options = {}) {
- options.wantsFocusCallback = true
- super(target, blueprint, options)
-
- /** @type {String[]} */
- this.key = this.options.key
- this.ctrlKey = options.ctrlKey ?? false
- this.shiftKey = options.shiftKey ?? false
- this.altKey = options.altKey ?? false
- this.metaKey = options.metaKey ?? false
-
- let self = this
- this.keyDownHandler = e => {
- if (
- e.code == self.key
- && e.ctrlKey === self.ctrlKey
- && e.shiftKey === self.shiftKey
- && e.altKey === self.altKey
- && e.metaKey === self.metaKey
- ) {
- self.fire()
- }
- }
- }
-
- /**
- *
- * @param {String} keyString
- * @returns {Object}
- */
- static keyOptionsParse(options, keyString) {
- options.key = keyString
- return options
- }
-
- blueprintFocused() {
- document.addEventListener("keydown", this.keyDownHandler)
- }
-
- blueprintUnfocused() {
- document.removeEventListener("keydown", this.keyDownHandler)
- }
-
- fire() {
- }
-}
+import Context from "./Context"
+
+export default class KeyboardShortcut extends Context {
+
+ constructor(target, blueprint, options = {}) {
+ options.wantsFocusCallback = true
+ super(target, blueprint, options)
+
+ /** @type {String[]} */
+ this.key = this.options.key
+ this.ctrlKey = options.ctrlKey ?? false
+ this.shiftKey = options.shiftKey ?? false
+ this.altKey = options.altKey ?? false
+ this.metaKey = options.metaKey ?? false
+
+ let self = this
+ this.keyDownHandler = e => {
+ if (
+ e.code == self.key
+ && e.ctrlKey === self.ctrlKey
+ && e.shiftKey === self.shiftKey
+ && e.altKey === self.altKey
+ && e.metaKey === self.metaKey
+ ) {
+ self.fire()
+ }
+ }
+ }
+
+ /**
+ *
+ * @param {String} keyString
+ * @returns {Object}
+ */
+ static keyOptionsParse(options, keyString) {
+ options.key = keyString
+ return options
+ }
+
+ blueprintFocused() {
+ document.addEventListener("keydown", this.keyDownHandler)
+ }
+
+ blueprintUnfocused() {
+ document.removeEventListener("keydown", this.keyDownHandler)
+ }
+
+ fire() {
+ }
+}
diff --git a/js/input/MouseTracking.js b/js/input/MouseTracking.js
old mode 100644
new mode 100755
index c8f9cf7..8cbf720
--- a/js/input/MouseTracking.js
+++ b/js/input/MouseTracking.js
@@ -1,22 +1,22 @@
-import Pointing from "./Pointing"
-
-export default class MouseTracking extends Pointing {
-
- constructor(target, blueprint, options = {}) {
- options.wantsFocusCallback = true
- super(target, blueprint, options)
-
- let self = this
- this.mousemoveHandler = e => {
- self.blueprint.entity.mousePosition = self.getLocation(e)
- }
- }
-
- blueprintFocused() {
- this.target.addEventListener("mousemove", this.mousemoveHandler)
- }
-
- blueprintUnfocused() {
- this.target.removeEventListener("mousemove", this.mousemoveHandler)
- }
-}
+import Pointing from "./Pointing"
+
+export default class MouseTracking extends Pointing {
+
+ constructor(target, blueprint, options = {}) {
+ options.wantsFocusCallback = true
+ super(target, blueprint, options)
+
+ let self = this
+ this.mousemoveHandler = e => {
+ self.blueprint.entity.mousePosition = self.getLocation(e)
+ }
+ }
+
+ blueprintFocused() {
+ this.target.addEventListener("mousemove", this.mousemoveHandler)
+ }
+
+ blueprintUnfocused() {
+ this.target.removeEventListener("mousemove", this.mousemoveHandler)
+ }
+}
diff --git a/js/input/Paste.js b/js/input/Paste.js
old mode 100644
new mode 100755
index 7559a1d..4198f99
--- a/js/input/Paste.js
+++ b/js/input/Paste.js
@@ -1,50 +1,50 @@
-import GraphNode from "../graph/GraphNode"
-import ObjectSerializer from "../serialization/ObjectSerializer"
-import Context from "./Context"
-
-export default class Paste extends Context {
-
- constructor(target, blueprint, options = {}) {
- options.wantsFocusCallback = true
- super(target, blueprint, options)
- this.serializer = new ObjectSerializer()
- let self = this
- this.pasteHandle = e => self.pasted(e.clipboardData.getData("Text"))
- }
-
- blueprintFocused() {
- document.body.addEventListener("paste", this.pasteHandle)
- }
-
- blueprintUnfocused() {
- document.body.removeEventListener("paste", this.pasteHandle)
- }
-
- pasted(value) {
- let top = 0
- let left = 0
- let count = 0
- let nodes = this.serializer.readMultiple(value).map(entity => {
- let node = new GraphNode(entity)
- top += node.location[1]
- left += node.location[0]
- ++count
- return node
- })
- top /= count
- left /= count
- if (nodes.length > 0) {
- this.blueprint.unselectAll()
- }
- let mousePosition = this.blueprint.entity.mousePosition
- this.blueprint.addGraphElement(...nodes)
- nodes.forEach(node => {
- const locationOffset = [
- mousePosition[0] - left,
- mousePosition[1] - top,
- ]
- node.addLocation(this.blueprint.compensateTranslation(locationOffset))
- node.setSelected(true)
- })
- }
-}
+import GraphNode from "../graph/GraphNode"
+import ObjectSerializer from "../serialization/ObjectSerializer"
+import Context from "./Context"
+
+export default class Paste extends Context {
+
+ constructor(target, blueprint, options = {}) {
+ options.wantsFocusCallback = true
+ super(target, blueprint, options)
+ this.serializer = new ObjectSerializer()
+ let self = this
+ this.pasteHandle = e => self.pasted(e.clipboardData.getData("Text"))
+ }
+
+ blueprintFocused() {
+ document.body.addEventListener("paste", this.pasteHandle)
+ }
+
+ blueprintUnfocused() {
+ document.body.removeEventListener("paste", this.pasteHandle)
+ }
+
+ pasted(value) {
+ let top = 0
+ let left = 0
+ let count = 0
+ let nodes = this.serializer.readMultiple(value).map(entity => {
+ let node = new GraphNode(entity)
+ top += node.location[1]
+ left += node.location[0]
+ ++count
+ return node
+ })
+ top /= count
+ left /= count
+ if (nodes.length > 0) {
+ this.blueprint.unselectAll()
+ }
+ let mousePosition = this.blueprint.entity.mousePosition
+ this.blueprint.addGraphElement(...nodes)
+ nodes.forEach(node => {
+ const locationOffset = [
+ mousePosition[0] - left,
+ mousePosition[1] - top,
+ ]
+ node.addLocation(this.blueprint.compensateTranslation(locationOffset))
+ node.setSelected(true)
+ })
+ }
+}
diff --git a/js/input/Unfocus.js b/js/input/Unfocus.js
old mode 100644
new mode 100755
index 32efaf6..6dd8234
--- a/js/input/Unfocus.js
+++ b/js/input/Unfocus.js
@@ -1,35 +1,35 @@
-import Context from "./Context"
-
-export default class Unfocus extends Context {
-
- constructor(target, blueprint, options = {}) {
- options.wantsFocusCallback = true
- super(target, blueprint, options)
-
- let self = this
- this.clickHandler = e => self.clickedSomewhere(e)
- if (this.blueprint.focuse) {
- document.addEventListener("click", this.clickHandler)
- }
- }
-
- /**
- *
- * @param {MouseEvent} e
- */
- clickedSomewhere(e) {
- // If target is inside the blueprint grid
- if (e.target.closest("ueb-blueprint")) {
- return
- }
- this.blueprint.setFocused(false)
- }
-
- blueprintFocused() {
- document.addEventListener("click", this.clickHandler)
- }
-
- blueprintUnfocused() {
- document.removeEventListener("click", this.clickHandler)
- }
-}
+import Context from "./Context"
+
+export default class Unfocus extends Context {
+
+ constructor(target, blueprint, options = {}) {
+ options.wantsFocusCallback = true
+ super(target, blueprint, options)
+
+ let self = this
+ this.clickHandler = e => self.clickedSomewhere(e)
+ if (this.blueprint.focuse) {
+ document.addEventListener("click", this.clickHandler)
+ }
+ }
+
+ /**
+ *
+ * @param {MouseEvent} e
+ */
+ clickedSomewhere(e) {
+ // If target is inside the blueprint grid
+ if (e.target.closest("ueb-blueprint")) {
+ return
+ }
+ this.blueprint.setFocused(false)
+ }
+
+ blueprintFocused() {
+ document.addEventListener("click", this.clickHandler)
+ }
+
+ blueprintUnfocused() {
+ document.removeEventListener("click", this.clickHandler)
+ }
+}
diff --git a/js/serialization/CustomSerializer.js b/js/serialization/CustomSerializer.js
old mode 100644
new mode 100755
index 02222df..ca242a9
--- a/js/serialization/CustomSerializer.js
+++ b/js/serialization/CustomSerializer.js
@@ -1,14 +1,14 @@
-import GeneralSerializer from "./GeneralSerializer"
-
-export default class CustomSerializer extends GeneralSerializer {
-
- constructor(objectWriter, entityType) {
- super(undefined, entityType)
- this.objectWriter = objectWriter
- }
-
- write(object) {
- let result = this.objectWriter(object)
- return result
- }
-}
+import GeneralSerializer from "./GeneralSerializer"
+
+export default class CustomSerializer extends GeneralSerializer {
+
+ constructor(objectWriter, entityType) {
+ super(undefined, entityType)
+ this.objectWriter = objectWriter
+ }
+
+ write(object) {
+ let result = this.objectWriter(object)
+ return result
+ }
+}
diff --git a/js/serialization/Grammar.js b/js/serialization/Grammar.js
index a52f1ae..5e6799b 100755
--- a/js/serialization/Grammar.js
+++ b/js/serialization/Grammar.js
@@ -113,25 +113,28 @@ export default class Grammar {
}
}
// Meta grammar
- static CreateAttributeGrammar = (r, attributeGrammar, attributeSupplier, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
- attributeGrammar.skip(valueSeparator)
+ static CreateAttributeGrammar = (r, entityType, valueSeparator = P.string("=").trim(P.optWhitespace)) =>
+ r.AttributeName.skip(valueSeparator)
.chain(attributeName => {
const attributeKey = attributeName.split(".")
- const attribute = attributeSupplier(attributeKey)
+ const attribute = Utility.objectGet(entityType.attributes, attributeKey)
let attributeValueGrammar = Grammar.getGrammarForType(r, attribute, r.AttributeAnyValue)
+ // Returns attributeSetter: a function called with an object as argument that will set the correct attribute value
return attributeValueGrammar.map(attributeValue =>
entity => Utility.objectSet(entity, attributeKey, attributeValue, true)
- ) // returns attributeSetter: a function called with an object as argument that will set the correct attribute value
+ )
})
// Meta grammar
- static CreateMultiAttributeGrammar = (r, keyGrammar, entityType, attributeSupplier) =>
+ static CreateMultiAttributeGrammar = (r, entityType) =>
/**
* Basically this creates a parser that looks for a string like 'Key (A=False,B="Something",)'
* Then it populates an object of type EntityType with the attribute values found inside the parentheses.
*/
P.seqMap(
- P.seq(keyGrammar, P.optWhitespace, P.string("(")),
- Grammar.CreateAttributeGrammar(r, r.AttributeName, attributeSupplier)
+ entityType.lookbehind
+ ? P.seq(P.string(entityType.lookbehind), P.optWhitespace, P.string("("))
+ : P.string("("),
+ Grammar.CreateAttributeGrammar(r, entityType)
.trim(P.optWhitespace)
.sepBy(P.string(","))
.skip(P.regex(/,?/).then(P.optWhitespace)), // Optional trailing comma
@@ -141,18 +144,8 @@ export default class Grammar {
attributes.forEach(attributeSetter => attributeSetter(result))
return result
})
- FunctionReference = r => Grammar.CreateMultiAttributeGrammar(
- r,
- P.succeed(),
- FunctionReferenceEntity,
- attributeKey => Utility.objectGet(FunctionReferenceEntity.attributes, attributeKey)
- )
- Pin = r => Grammar.CreateMultiAttributeGrammar(
- r,
- P.string("Pin"),
- PinEntity,
- attributeKey => Utility.objectGet(PinEntity.attributes, attributeKey)
- )
+ FunctionReference = r => Grammar.CreateMultiAttributeGrammar(r, FunctionReferenceEntity)
+ Pin = r => Grammar.CreateMultiAttributeGrammar(r, PinEntity)
CustomProperties = r =>
P.string("CustomProperties")
.then(P.whitespace)
@@ -169,7 +162,7 @@ export default class Grammar {
P
.alt(
r.CustomProperties,
- Grammar.CreateAttributeGrammar(r, r.AttributeName, attributeKey => Utility.objectGet(ObjectEntity.attributes, attributeKey))
+ Grammar.CreateAttributeGrammar(r, ObjectEntity)
)
.sepBy1(P.whitespace),
P.seq(r.WhitespaceNewline, P.string("End"), P.whitespace, P.string("Object")),
diff --git a/js/serialization/ToStringSerializer.js b/js/serialization/ToStringSerializer.js
old mode 100644
new mode 100755
index 10b4f1f..560500e
--- a/js/serialization/ToStringSerializer.js
+++ b/js/serialization/ToStringSerializer.js
@@ -1,13 +1,13 @@
-import GeneralSerializer from "./GeneralSerializer"
-
-export default class ToStringSerializer extends GeneralSerializer {
-
- constructor(entityType) {
- super(undefined, entityType)
- }
-
- write(object) {
- let result = object.toString()
- return result
- }
-}
+import GeneralSerializer from "./GeneralSerializer"
+
+export default class ToStringSerializer extends GeneralSerializer {
+
+ constructor(entityType) {
+ super(undefined, entityType)
+ }
+
+ write(object) {
+ let result = object.toString()
+ return result
+ }
+}
diff --git a/js/serialization/initializeSerializerFactory.js b/js/serialization/initializeSerializerFactory.js
old mode 100644
new mode 100755
index 93feb94..2986f36
--- a/js/serialization/initializeSerializerFactory.js
+++ b/js/serialization/initializeSerializerFactory.js
@@ -1,50 +1,50 @@
-import CustomSerializer from "./CustomSerializer"
-import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
-import GeneralSerializer from "./GeneralSerializer"
-import GuidEntity from "../entity/GuidEntity"
-import IntegerEntity from "../entity/IntegerEntity"
-import LocalizedTextEntity from "../entity/LocalizedTextEntity"
-import ObjectEntity from "../entity/ObjectEntity"
-import ObjectReferenceEntity from "../entity/ObjectReferenceEntity"
-import ObjectSerializer from "./ObjectSerializer"
-import PathSymbolEntity from "../entity/PathSymbolEntity"
-import PinEntity from "../entity/PinEntity"
-import PinReferenceEntity from "../entity/PinReferenceEntity"
-import SerializerFactory from "./SerializerFactory"
-import ToStringSerializer from "./ToStringSerializer"
-
-export default function initializeSerializerFactory() {
- SerializerFactory.registerSerializer(
- ObjectEntity,
- new ObjectSerializer()
- )
- SerializerFactory.registerSerializer(
- PinEntity,
- new GeneralSerializer(v => `Pin (${v})`, PinEntity, "", ",", true)
- )
- SerializerFactory.registerSerializer(
- FunctionReferenceEntity,
- new GeneralSerializer(v => `(${v})`, FunctionReferenceEntity, "", ",", false)
- )
- SerializerFactory.registerSerializer(
- LocalizedTextEntity,
- new GeneralSerializer(v => `NSLOCTEXT(${v})`, LocalizedTextEntity, "", ",", false, "", _ => "")
- )
- SerializerFactory.registerSerializer(
- PinReferenceEntity,
- new GeneralSerializer(v => v, PinReferenceEntity, "", " ", false, "", _ => "")
- )
- SerializerFactory.registerSerializer(
- ObjectReferenceEntity,
- new CustomSerializer(
- /** @param {ObjectReferenceEntity} objectReference */
- objectReference => (objectReference.type ?? "") + (
- objectReference.path
- ? objectReference.type ? `'"${objectReference.path}"'` : objectReference.path
- : ""
- ))
- )
- SerializerFactory.registerSerializer(PathSymbolEntity, new ToStringSerializer(PathSymbolEntity))
- SerializerFactory.registerSerializer(GuidEntity, new ToStringSerializer(GuidEntity))
- SerializerFactory.registerSerializer(IntegerEntity, new ToStringSerializer(IntegerEntity))
-}
+import CustomSerializer from "./CustomSerializer"
+import FunctionReferenceEntity from "../entity/FunctionReferenceEntity"
+import GeneralSerializer from "./GeneralSerializer"
+import GuidEntity from "../entity/GuidEntity"
+import IntegerEntity from "../entity/IntegerEntity"
+import LocalizedTextEntity from "../entity/LocalizedTextEntity"
+import ObjectEntity from "../entity/ObjectEntity"
+import ObjectReferenceEntity from "../entity/ObjectReferenceEntity"
+import ObjectSerializer from "./ObjectSerializer"
+import PathSymbolEntity from "../entity/PathSymbolEntity"
+import PinEntity from "../entity/PinEntity"
+import PinReferenceEntity from "../entity/PinReferenceEntity"
+import SerializerFactory from "./SerializerFactory"
+import ToStringSerializer from "./ToStringSerializer"
+
+export default function initializeSerializerFactory() {
+ SerializerFactory.registerSerializer(
+ ObjectEntity,
+ new ObjectSerializer()
+ )
+ SerializerFactory.registerSerializer(
+ PinEntity,
+ new GeneralSerializer(v => `Pin (${v})`, PinEntity, "", ",", true)
+ )
+ SerializerFactory.registerSerializer(
+ FunctionReferenceEntity,
+ new GeneralSerializer(v => `(${v})`, FunctionReferenceEntity, "", ",", false)
+ )
+ SerializerFactory.registerSerializer(
+ LocalizedTextEntity,
+ new GeneralSerializer(v => `NSLOCTEXT(${v})`, LocalizedTextEntity, "", ",", false, "", _ => "")
+ )
+ SerializerFactory.registerSerializer(
+ PinReferenceEntity,
+ new GeneralSerializer(v => v, PinReferenceEntity, "", " ", false, "", _ => "")
+ )
+ SerializerFactory.registerSerializer(
+ ObjectReferenceEntity,
+ new CustomSerializer(
+ /** @param {ObjectReferenceEntity} objectReference */
+ objectReference => (objectReference.type ?? "") + (
+ objectReference.path
+ ? objectReference.type ? `'"${objectReference.path}"'` : objectReference.path
+ : ""
+ ))
+ )
+ SerializerFactory.registerSerializer(PathSymbolEntity, new ToStringSerializer(PathSymbolEntity))
+ SerializerFactory.registerSerializer(GuidEntity, new ToStringSerializer(GuidEntity))
+ SerializerFactory.registerSerializer(IntegerEntity, new ToStringSerializer(IntegerEntity))
+}
diff --git a/js/template/LinkTemplate.js b/js/template/LinkTemplate.js
old mode 100644
new mode 100755
index 05e51a6..7f1889f
--- a/js/template/LinkTemplate.js
+++ b/js/template/LinkTemplate.js
@@ -1,49 +1,49 @@
-import html from "./html"
-import Template from "./Template"
-
-/**
- * @typedef {import("../graph/GraphLink").default} GraphLink
- */
-export default class LinkTemplate extends Template {
-
- /**
- * Computes the html content of the target element.
- * @param {GraphLink} link Link connecting two graph nodes
- * @returns The result html
- */
- render(link) {
- return html`
-
- `
- }
-
- /**
- * Applies the style to the element.
- * @param {GraphLink} link Element of the graph
- */
- apply(link) {
- super.apply(link)
-
- }
-
- /**
- * Applies the style relative to the source pin location.
- * @param {GraphLink} link Link element
- */
- applySourceLocation(link, initialPosition) {
- // Set initial position
- link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]))
- link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]))
- }
-
- /**
- * Applies the style relative to the destination pin location.
- * @param {GraphLink} link Link element
- */
- applyDestinationLocation(link, finalPosition) {
- link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]))
- link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]))
- }
-}
+import html from "./html"
+import Template from "./Template"
+
+/**
+ * @typedef {import("../graph/GraphLink").default} GraphLink
+ */
+export default class LinkTemplate extends Template {
+
+ /**
+ * Computes the html content of the target element.
+ * @param {GraphLink} link Link connecting two graph nodes
+ * @returns The result html
+ */
+ render(link) {
+ return html`
+
+ `
+ }
+
+ /**
+ * Applies the style to the element.
+ * @param {GraphLink} link Element of the graph
+ */
+ apply(link) {
+ super.apply(link)
+
+ }
+
+ /**
+ * Applies the style relative to the source pin location.
+ * @param {GraphLink} link Link element
+ */
+ applySourceLocation(link, initialPosition) {
+ // Set initial position
+ link.style.setProperty("--ueb-link-from-x", sanitizeText(initialPosition[0]))
+ link.style.setProperty("--ueb-link-from-y", sanitizeText(initialPosition[1]))
+ }
+
+ /**
+ * Applies the style relative to the destination pin location.
+ * @param {GraphLink} link Link element
+ */
+ applyDestinationLocation(link, finalPosition) {
+ link.style.setProperty("--ueb-link-to-x", sanitizeText(finalPosition[0]))
+ link.style.setProperty("--ueb-link-to-y", sanitizeText(finalPosition[1]))
+ }
+}
diff --git a/js/template/PinTemplate.js b/js/template/PinTemplate.js
old mode 100644
new mode 100755
index 156207b..f906900
--- a/js/template/PinTemplate.js
+++ b/js/template/PinTemplate.js
@@ -1,38 +1,38 @@
-import html from "./html"
-import sanitizeText from "./sanitizeText"
-import Template from "./Template"
-
-/**
- * @typedef {import("../graph/GraphPin").default} GraphPin
- */
-export default class PinTemplate extends Template {
-
- /**
- * Computes the html content of the pin.
- * @param {GraphPin} pin Pin entity
- * @returns The result html
- */
- render(pin) {
- if (pin.isInput()) {
- return html`
-
- ${sanitizeText(pin.getPinDisplayName())}
- `
- } else {
- return html`
- ${sanitizeText(pin.getPinDisplayName())}
-
- `
- }
- }
-
- /**
- * Applies the style to the element.
- * @param {GraphPin} pin Element of the graph
- */
- apply(pin) {
- super.apply(pin)
- pin.classList.add("ueb-node-" + pin.isInput() ? "input" : "output", "ueb-node-value-" + sanitizeText(pin.getType()))
- pin.clickableElement = pin.querySelector(".ueb-node-value-icon")
- }
+import html from "./html"
+import sanitizeText from "./sanitizeText"
+import Template from "./Template"
+
+/**
+ * @typedef {import("../graph/GraphPin").default} GraphPin
+ */
+export default class PinTemplate extends Template {
+
+ /**
+ * Computes the html content of the pin.
+ * @param {GraphPin} pin Pin entity
+ * @returns The result html
+ */
+ render(pin) {
+ if (pin.isInput()) {
+ return html`
+
+ ${sanitizeText(pin.getPinDisplayName())}
+ `
+ } else {
+ return html`
+ ${sanitizeText(pin.getPinDisplayName())}
+
+ `
+ }
+ }
+
+ /**
+ * Applies the style to the element.
+ * @param {GraphPin} pin Element of the graph
+ */
+ apply(pin) {
+ super.apply(pin)
+ pin.classList.add("ueb-node-" + pin.isInput() ? "input" : "output", "ueb-node-value-" + sanitizeText(pin.getType()))
+ pin.clickableElement = pin.querySelector(".ueb-node-value-icon")
+ }
}
\ No newline at end of file
diff --git a/js/template/SelectableDraggableTemplate.js b/js/template/SelectableDraggableTemplate.js
old mode 100644
new mode 100755
index c5ca426..829c9c6
--- a/js/template/SelectableDraggableTemplate.js
+++ b/js/template/SelectableDraggableTemplate.js
@@ -1,29 +1,29 @@
-import sanitizeText from "./sanitizeText"
-import Template from "./Template"
-
-/**
- * @typedef {import("../graph/SelectableDraggable").default} SelectableDraggable
- */
-export default class SelectableDraggableTemplate extends Template {
-
- /**
- * Returns the html elements rendered from this template.
- * @param {SelectableDraggable} element Element of the graph
- */
- applyLocation(element) {
- element.style.setProperty("--ueb-position-x", sanitizeText(element.location[0]))
- element.style.setProperty("--ueb-position-y", sanitizeText(element.location[1]))
- }
-
- /**
- * Returns the html elements rendered from this template.
- * @param {SelectableDraggable} element Element of the graph
- */
- applySelected(element) {
- if (element.selected) {
- element.classList.add("ueb-selected")
- } else {
- element.classList.remove("ueb-selected")
- }
- }
-}
+import sanitizeText from "./sanitizeText"
+import Template from "./Template"
+
+/**
+ * @typedef {import("../graph/SelectableDraggable").default} SelectableDraggable
+ */
+export default class SelectableDraggableTemplate extends Template {
+
+ /**
+ * Returns the html elements rendered from this template.
+ * @param {SelectableDraggable} element Element of the graph
+ */
+ applyLocation(element) {
+ element.style.setProperty("--ueb-position-x", sanitizeText(element.location[0]))
+ element.style.setProperty("--ueb-position-y", sanitizeText(element.location[1]))
+ }
+
+ /**
+ * Returns the html elements rendered from this template.
+ * @param {SelectableDraggable} element Element of the graph
+ */
+ applySelected(element) {
+ if (element.selected) {
+ element.classList.add("ueb-selected")
+ } else {
+ element.classList.remove("ueb-selected")
+ }
+ }
+}
diff --git a/js/template/SelectorTemplate.js b/js/template/SelectorTemplate.js
old mode 100644
new mode 100755
index 5430e8c..5b653ee
--- a/js/template/SelectorTemplate.js
+++ b/js/template/SelectorTemplate.js
@@ -1,49 +1,49 @@
-import sanitizeText from "./sanitizeText"
-import Template from "./Template"
-
-/**
- * @typedef {import("../graph/GraphSelector").default} GraphSelector
- */
-export default class SelectorTemplate extends Template {
-
- /**
- * Applies the style to the element.
- * @param {GraphSelector} selector Selector element
- */
- apply(selector) {
- super.apply(selector)
- selector.classList.add("ueb-selector")
- this.applyFinishSelecting(selector)
- }
-
- /**
- * Applies the style relative to selection beginning.
- * @param {GraphSelector} selector Selector element
- */
- applyStartSelecting(selector, initialPosition) {
- // Set initial position
- selector.style.setProperty("--ueb-select-from-x", sanitizeText(initialPosition[0]))
- selector.style.setProperty("--ueb-select-from-y", sanitizeText(initialPosition[1]))
- // Final position coincide with the initial position, at the beginning of selection
- selector.style.setProperty("--ueb-select-to-x", sanitizeText(initialPosition[0]))
- selector.style.setProperty("--ueb-select-to-y", sanitizeText(initialPosition[1]))
- selector.dataset.selecting = "true"
- }
-
- /**
- * Applies the style relative to selection.
- * @param {GraphSelector} selector Selector element
- */
- applyDoSelecting(selector, finalPosition) {
- selector.style.setProperty("--ueb-select-to-x", sanitizeText(finalPosition[0]))
- selector.style.setProperty("--ueb-select-to-y", sanitizeText(finalPosition[1]))
- }
-
- /**
- * Applies the style relative to selection finishing.
- * @param {GraphSelector} selector Selector element
- */
- applyFinishSelecting(selector) {
- selector.dataset.selecting = "false"
- }
-}
+import sanitizeText from "./sanitizeText"
+import Template from "./Template"
+
+/**
+ * @typedef {import("../graph/GraphSelector").default} GraphSelector
+ */
+export default class SelectorTemplate extends Template {
+
+ /**
+ * Applies the style to the element.
+ * @param {GraphSelector} selector Selector element
+ */
+ apply(selector) {
+ super.apply(selector)
+ selector.classList.add("ueb-selector")
+ this.applyFinishSelecting(selector)
+ }
+
+ /**
+ * Applies the style relative to selection beginning.
+ * @param {GraphSelector} selector Selector element
+ */
+ applyStartSelecting(selector, initialPosition) {
+ // Set initial position
+ selector.style.setProperty("--ueb-select-from-x", sanitizeText(initialPosition[0]))
+ selector.style.setProperty("--ueb-select-from-y", sanitizeText(initialPosition[1]))
+ // Final position coincide with the initial position, at the beginning of selection
+ selector.style.setProperty("--ueb-select-to-x", sanitizeText(initialPosition[0]))
+ selector.style.setProperty("--ueb-select-to-y", sanitizeText(initialPosition[1]))
+ selector.dataset.selecting = "true"
+ }
+
+ /**
+ * Applies the style relative to selection.
+ * @param {GraphSelector} selector Selector element
+ */
+ applyDoSelecting(selector, finalPosition) {
+ selector.style.setProperty("--ueb-select-to-x", sanitizeText(finalPosition[0]))
+ selector.style.setProperty("--ueb-select-to-y", sanitizeText(finalPosition[1]))
+ }
+
+ /**
+ * Applies the style relative to selection finishing.
+ * @param {GraphSelector} selector Selector element
+ */
+ applyFinishSelecting(selector) {
+ selector.dataset.selecting = "false"
+ }
+}
diff --git a/js/template/html.js b/js/template/html.js
old mode 100644
new mode 100755
index 73b15be..856a94c
--- a/js/template/html.js
+++ b/js/template/html.js
@@ -1,2 +1,2 @@
-const html = String.raw
-export default html
+const html = String.raw
+export default html
diff --git a/js/template/sanitizeText.js b/js/template/sanitizeText.js
old mode 100644
new mode 100755
index bd75b4c..2802629
--- a/js/template/sanitizeText.js
+++ b/js/template/sanitizeText.js
@@ -1,18 +1,18 @@
-const div = document.createElement("div")
-
-const tagReplacement = {
- '&': '&',
- '<': '<',
- '>': '>',
- "'": ''',
- '"': '"'
-}
-
-function sanitizeText(value) {
- if (value.constructor === String) {
- return value.replace(/[&<>'"]/g, tag => tagReplacement[tag])
- }
- return value
-}
-
+const div = document.createElement("div")
+
+const tagReplacement = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ "'": ''',
+ '"': '"'
+}
+
+function sanitizeText(value) {
+ if (value.constructor === String) {
+ return value.replace(/[&<>'"]/g, tag => tagReplacement[tag])
+ }
+ return value
+}
+
export default sanitizeText
\ No newline at end of file
diff --git a/package.json b/package.json
old mode 100644
new mode 100755
index 2433244..064e9be
--- a/package.json
+++ b/package.json
@@ -1,37 +1,37 @@
-{
- "name": "ueblueprint",
- "version": "1.0.0",
- "description": "Unreal Engine's Blueprint visualisation library",
- "main": "ueblueprint.js",
- "scripts": {
- "build": "rollup --config && sass scss:dist/css --style=compressed"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/barsdeveloper/ueblueprint.git"
- },
- "keywords": [
- "unreal",
- "engine",
- "blueprint"
- ],
- "author": "barsdeveloper",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/barsdeveloper/ueblueprint/issues"
- },
- "homepage": "https://github.com/barsdeveloper/ueblueprint#readme",
- "devDependencies": {
- "@rollup/plugin-commonjs": "^21.0.0",
- "@rollup/plugin-node-resolve": "^13.0.5",
- "rollup": "^2.58.0",
- "rollup-plugin-copy": "^3.4.0",
- "rollup-plugin-minify-html-template-literals": "^1.2.0",
- "rollup-plugin-terser": "^7.0.2",
- "sass": "^1.45.1",
- "terser": "^5.9.0"
- },
- "dependencies": {
- "parsimmon": "^1.18.0"
- }
-}
\ No newline at end of file
+{
+ "name": "ueblueprint",
+ "version": "1.0.0",
+ "description": "Unreal Engine's Blueprint visualisation library",
+ "main": "ueblueprint.js",
+ "scripts": {
+ "build": "rollup --config && sass scss:dist/css --style=compressed"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/barsdeveloper/ueblueprint.git"
+ },
+ "keywords": [
+ "unreal",
+ "engine",
+ "blueprint"
+ ],
+ "author": "barsdeveloper",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/barsdeveloper/ueblueprint/issues"
+ },
+ "homepage": "https://github.com/barsdeveloper/ueblueprint#readme",
+ "devDependencies": {
+ "@rollup/plugin-commonjs": "^21.0.0",
+ "@rollup/plugin-node-resolve": "^13.0.5",
+ "rollup": "^2.58.0",
+ "rollup-plugin-copy": "^3.4.0",
+ "rollup-plugin-minify-html-template-literals": "^1.2.0",
+ "rollup-plugin-terser": "^7.0.2",
+ "sass": "^1.45.1",
+ "terser": "^5.9.0"
+ },
+ "dependencies": {
+ "parsimmon": "^1.18.0"
+ }
+}
diff --git a/rollup.config.js b/rollup.config.js
old mode 100644
new mode 100755
index b0129ba..5b42cc6
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,27 +1,27 @@
-import { nodeResolve } from '@rollup/plugin-node-resolve'
-import minifyHTML from 'rollup-plugin-minify-html-template-literals'
-import commonjs from '@rollup/plugin-commonjs'
-import { terser } from 'rollup-plugin-terser'
-import copy from 'rollup-plugin-copy'
-
-export default {
- input: 'js/export.js',
- output: {
- file: 'dist/ueblueprint.js',
- format: 'es'
- },
- plugins: [
- nodeResolve({ browser: true }),
- //minifyHTML(),
- commonjs(),
- //terser()
- copy({
- targets: [
- {
- src: ["font/*"],
- dest: "dist/font"
- }
- ]
- })
- ]
+import { nodeResolve } from '@rollup/plugin-node-resolve'
+import minifyHTML from 'rollup-plugin-minify-html-template-literals'
+import commonjs from '@rollup/plugin-commonjs'
+import { terser } from 'rollup-plugin-terser'
+import copy from 'rollup-plugin-copy'
+
+export default {
+ input: 'js/export.js',
+ output: {
+ file: 'dist/ueblueprint.js',
+ format: 'es'
+ },
+ plugins: [
+ nodeResolve({ browser: true }),
+ //minifyHTML(),
+ commonjs(),
+ //terser()
+ copy({
+ targets: [
+ {
+ src: ["font/*"],
+ dest: "dist/font"
+ }
+ ]
+ })
+ ]
}
\ No newline at end of file
diff --git a/scss/ueblueprint-node-value-type-color.scss b/scss/ueblueprint-node-value-type-color.scss
old mode 100644
new mode 100755
index 4f9aa69..201db48
--- a/scss/ueblueprint-node-value-type-color.scss
+++ b/scss/ueblueprint-node-value-type-color.scss
@@ -1,45 +1,45 @@
-.ueb {
- $ueb-node-value-color : white;
- --ueb-node-value-color: #{$ueb-node-value-color};
-}
-
-.ueb-node-value-boolean {
- $ueb-node-value-color : #930000;
- --ueb-node-value-color: #{$ueb-node-value-color};
-}
-
-.ueb-node-value-integer {
- $ueb-node-value-color : #1fe0ad;
- --ueb-node-value-color: #{$ueb-node-value-color};
-}
-
-.ueb-node-value-float {
- $ueb-node-value-color : #9ffb44;
- --ueb-node-value-color: #{$ueb-node-value-color};
-}
-
-.ueb-node-value-vector {
- $ueb-node-value-color : #fcc823;
- --ueb-node-value-color: #{$ueb-node-value-color};
-}
-
-.ueb-node-value-rotator {
- $ueb-node-value-color : #9eb1fc;
- --ueb-node-value-color: #{$ueb-node-value-color};
-}
-
-.ueb-node-value-string {
- $ueb-node-value-color : #fc00d2;
- --ueb-node-value-color : #{$ueb-node-value-color};
- --ueb-node-value-background: linear-gradient(90deg, #fc00d220, #fc00d280 15%, #fc00d250 85%, transparent);
-}
-
-.ueb-node-value-name {
- $ueb-node-value-color : #cb81fc;
- --ueb-node-value-color: #{$ueb-node-value-color};
-}
-
-.ueb-node-value-objectreference {
- $ueb-node-value-color : #00a8f2;
- --ueb-node-value-color: #{$ueb-node-value-color};
+.ueb {
+ $ueb-node-value-color : white;
+ --ueb-node-value-color: #{$ueb-node-value-color};
+}
+
+.ueb-node-value-boolean {
+ $ueb-node-value-color : #930000;
+ --ueb-node-value-color: #{$ueb-node-value-color};
+}
+
+.ueb-node-value-integer {
+ $ueb-node-value-color : #1fe0ad;
+ --ueb-node-value-color: #{$ueb-node-value-color};
+}
+
+.ueb-node-value-float {
+ $ueb-node-value-color : #9ffb44;
+ --ueb-node-value-color: #{$ueb-node-value-color};
+}
+
+.ueb-node-value-vector {
+ $ueb-node-value-color : #fcc823;
+ --ueb-node-value-color: #{$ueb-node-value-color};
+}
+
+.ueb-node-value-rotator {
+ $ueb-node-value-color : #9eb1fc;
+ --ueb-node-value-color: #{$ueb-node-value-color};
+}
+
+.ueb-node-value-string {
+ $ueb-node-value-color : #fc00d2;
+ --ueb-node-value-color : #{$ueb-node-value-color};
+ --ueb-node-value-background: linear-gradient(90deg, #fc00d220, #fc00d280 15%, #fc00d250 85%, transparent);
+}
+
+.ueb-node-value-name {
+ $ueb-node-value-color : #cb81fc;
+ --ueb-node-value-color: #{$ueb-node-value-color};
+}
+
+.ueb-node-value-objectreference {
+ $ueb-node-value-color : #00a8f2;
+ --ueb-node-value-color: #{$ueb-node-value-color};
}
\ No newline at end of file
diff --git a/scss/ueblueprint-style.css b/scss/ueblueprint-style.css
old mode 100644
new mode 100755
index ad0a6b9..b9e766f
--- a/scss/ueblueprint-style.css
+++ b/scss/ueblueprint-style.css
@@ -1,431 +1,431 @@
-@font-face {
- font-family: "Roboto";
- font-style : light;
- src :
- url("../font/roboto-light.woff2") format("woff2"),
- url("../font/roboto-light.woff") format("woff");
-}
-
-@font-face {
- font-family: "Roboto";
- font-style : regular;
- src :
- url("../font/roboto-regular.woff2") format("woff2"),
- url("../font/roboto-regular.woff") format("woff");
-}
-
-:root {
- --ueb-fron-size : 13px;
- --ueb-viewport-height : 30rem;
- --ueb-viewport-width : 100%;
- --ueb-grid-size : 16px;
- --ueb-grid-line-width : 2px;
- --ueb-grid-line-color : #353535;
- --ueb-grid-set : 8;
- --ueb-grid-set-line-color : #161616;
- --ueb-grid-axis-line-color: black;
- --ueb-grid-snap : 16px;
- --ueb-node-radius : 8px;
-}
-
-ueb-blueprint {
- display : block;
- position : relative;
- font-family: Roboto, Noto, Oxygen, Ubuntu, "Open Sans", "Helvetica Neue", sans-serif;
- font-size : var(--ueb-fron-size);
- user-select: none;
-}
-
-.ueb-viewport-header {
- display : flex;
- position : absolute;
- top : 0;
- right : 0;
- left : 0;
- height : 1.5em;
- background: rgba(0, 0, 0, 0.5);
- z-index : 1;
-}
-
-.ueb-viewport-zoom {
- color: #4d4d4db7;
-}
-
-.ueb-viewport-body {
- position : relative;
- height : var(--ueb-viewport-height);
- width : var(--ueb-viewport-width);
- overflow : hidden;
- scrollbar-width: 0;
-}
-
-ueb-blueprint[data-focused="true"] .ueb-viewport-body {
- overflow: scroll;
-}
-
-.ueb-grid {
- --ueb-grid-line-actual-width: calc(var(--ueb-grid-line-width) / var(--ueb-scale));
- position : absolute;
- min-width : 100%;
- min-height : 100%;
- width : calc((100% + var(--ueb-additional-x) * 1px) / var(--ueb-scale));
- height : calc((100% + var(--ueb-additional-y) * 1px) / var(--ueb-scale));
- background-color : #262626;
- background-image :
- /* Axis lines */
- linear-gradient(var(--ueb-grid-axis-line-color),
- var(--ueb-grid-axis-line-color)),
- linear-gradient(var(--ueb-grid-axis-line-color),
- var(--ueb-grid-axis-line-color)),
- /* Dark bigger grid */
- linear-gradient(to right,
- var(--ueb-grid-set-line-color),
- var(--ueb-grid-set-line-color) var(--ueb-grid-line-actual-width),
- transparent var(--ueb-grid-line-actual-width),
- transparent),
- linear-gradient(to bottom,
- var(--ueb-grid-set-line-color),
- var(--ueb-grid-set-line-color) var(--ueb-grid-line-actual-width),
- transparent var(--ueb-grid-line-actual-width),
- transparent),
- /* Light grid */
- linear-gradient(to right,
- var(--ueb-grid-line-color),
- var(--ueb-grid-line-color) var(--ueb-grid-line-actual-width),
- transparent var(--ueb-grid-line-actual-width),
- transparent),
- linear-gradient(to bottom,
- var(--ueb-grid-line-color),
- var(--ueb-grid-line-color) var(--ueb-grid-line-actual-width),
- transparent var(--ueb-grid-line-actual-width),
- transparent);
- background-size:
- /* Axis lines */
- 100% var(--ueb-grid-line-actual-width),
- var(--ueb-grid-line-actual-width) 100%,
- /* Dark bigger grid */
- calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)) calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)),
- calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)) calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)),
- /* Light grid */
- var(--ueb-grid-actual-size) var(--ueb-grid-actual-size),
- var(--ueb-grid-actual-size) var(--ueb-grid-actual-size);
- background-position: calc(var(--ueb-translate-x) * 1px) calc(var(--ueb-translate-y) * 1px);
- background-repeat : repeat-x, repeat-y, repeat, repeat, repeat, repeat;
- transform : scale(var(--ueb-scale), var(--ueb-scale));
- transform-origin : 0 0;
- overflow : hidden;
-}
-
-.ueb-grid[data-drag-scrolling="true"] {
- cursor: grabbing;
-}
-
-.ueb-zoom--.ueb,
-.ueb {
- /* 16/16 */
- --ueb-scale : 1;
- --ueb-grid-actual-size: var(--ueb-grid-size);
-}
-
-.ueb-zoom--1.ueb {
- /* 14/16 */
- --ueb-scale: 0.875;
-}
-
-.ueb-zoom--2.ueb {
- /* 12/16 */
- --ueb-scale: 0.75;
-}
-
-.ueb-zoom--3.ueb {
- /* 10.8/16 */
- --ueb-scale: 0.675;
-}
-
-.ueb-zoom--4.ueb {
- /* 8/16 */
- --ueb-scale : 0.5;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 2);
-}
-
-.ueb-zoom--5.ueb {
- /* 6/16 */
- --ueb-scale : 0.375;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 2);
-}
-
-.ueb-zoom--6.ueb {
- --ueb-scale : 0.333333;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
-}
-
-.ueb-zoom--7.ueb {
- --ueb-scale : 0.3;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
-}
-
-.ueb-zoom--8.ueb {
- --ueb-scale : 0.266666;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
-}
-
-.ueb-zoom--9.ueb {
- --ueb-scale : 0.233333;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
-}
-
-.ueb-zoom--10.ueb {
- /* 12/16 */
- --ueb-scale : 0.2;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
-}
-
-.ueb-zoom--11.ueb {
- /* 12/16 */
- --ueb-scale : 0.166666;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 6);
-}
-
-.ueb-zoom--12.ueb {
- /* 12/16 */
- --ueb-scale : 0.133333;
- --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 6);
-}
-
-.ueb-grid-content {
- position : relative;
- width : 0;
- height : 0;
- transform: translateX(calc(var(--ueb-translate-x) * 1px)) translateY(calc(var(--ueb-translate-y) * 1px));
-}
-
-ueb-node {
- display : block;
- position : absolute;
- transform : translateX(calc(var(--ueb-position-x) * 1px)) translateY(calc(var(--ueb-position-y) * 1px));
- border-radius: var(--ueb-node-radius);
- box-shadow : 0 0 1px 0 black, 1px 4px 6px 0 rgba(0, 0, 0, 0.3);
- will-change : transform;
-}
-
-.ueb-grid[data-drag-scrolling="false"] ueb-selector[data-selecting="false"]~ueb-node {
- cursor: move;
-}
-
-.ueb-node-border {
- margin : -3px;
- padding : 3px;
- border-radius: calc(var(--ueb-node-radius) * 1.4);
-}
-
-.ueb-selected {
- z-index: 1;
-}
-
-.ueb-selected>.ueb-node-border {
- background-image:
- linear-gradient(to right, #f1b000 0%, #f1b000 100%),
- linear-gradient(to bottom, #f1b000 0%, #cc6700 100%),
- linear-gradient(to right, #cc6700 0%, #cc6700 100%),
- linear-gradient(to bottom, #f1b000 0%, #cc6700 100%);
- background-size : 100% 7px, 7px 100%, 100% 7px, 7px 100%;
- background-position: top, right, bottom, left;
- background-repeat : repeat-x, repeat-y, repeat-x, repeat-y;
- outline : 3px solid #cc6700;
- outline-offset : -6px;
-}
-
-.ueb-node-content {
- position : relative;
- padding : 1px;
- box-shadow : inset 0 0 2px 0 black;
- border-radius: var(--ueb-node-radius);
- background : rgba(0, 0, 0, 0.7);
- overflow : hidden;
-}
-
-.ueb-node-header {
- padding : 0.2em 0.7em;
- box-shadow : inset 0 1px 2px 0 #313631, inset 0 2px 0 0 #92c381;
- border-radius: var(--ueb-node-radius) var(--ueb-node-radius) 0 0;
- background : linear-gradient(170deg, #5f815a 0%, #5f815a 50%, transparent 100%);
- color : #c0c0c0;
- font-weight : 600;
- white-space : nowrap;
-}
-
-.ueb-node-name {
- background: radial-gradient(closest-side, rgba(0, 0, 0, 0.5) 0%, transparent 90%);
- margin : -0.1em -1.6em;
- padding : 0.1em 1.6em;
-}
-
-.ueb-node-body {
- display : flex;
- padding : 6px 0;
- color : white;
- font-weight: 100;
- white-space: nowrap;
-}
-
-.ueb-node-inputs {
- margin-right: auto;
- padding-left: 8px;
-}
-
-.ueb-node-outputs {
- padding-right: 8px;
-}
-
-ueb-pin {
- display: block;
- padding: 1px 2px;
-}
-
-.ueb-grid[data-drag-scrolling="false"] {
- cursor: default;
-}
-
-ueb-selector[data-selecting="false"]~ueb-node ueb-pin:hover {
- background: var(--ueb-node-value-background);
-}
-
-.ueb-grid[data-drag-scrolling="false"] ueb-selector[data-selecting="false"]~ueb-node ueb-pin .ueb-node-value-icon {
- cursor: crosshair;
-}
-
-.ueb-node-value-icon {
- display : inline-block;
- position : relative;
- width : 0.85em;
- height : 0.85em;
- vertical-align: baseline;
- margin : 0 0.4em -1px 0.1em;
-}
-
-.ueb-node-value-icon::before {
- content : "";
- display : block;
- position : absolute;
- top : 0;
- right : 0;
- bottom : 0;
- left : 0;
- border : 2px solid var(--ueb-node-value-color);
- border-radius: 50%;
-}
-
-.ueb-node-value-fill::before {
- background: var(--ueb-node-value-color);
-}
-
-.ueb-node-value-icon::after {
- content : "";
- display : block;
- position : absolute;
- top : calc(50% - 0.3em);
- left : calc(100% + 1px);
- width : 0;
- height : 0;
- border-top : 0.3em solid transparent;
- border-bottom: 0.3em solid transparent;
- border-left : 0.3em solid var(--ueb-node-value-color);
-}
-
-.ueb-selector {
- display : block;
- position : absolute;
- visibility: hidden;
- top : 0;
- left : 0;
- width : 0;
- height : 0;
- background-image:
- /* Top */
- repeating-linear-gradient(90deg,
- transparent,
- transparent calc(1px / var(--ueb-scale)),
- white calc(2px / var(--ueb-scale)),
- white calc(7px / var(--ueb-scale)),
- transparent calc(7px / var(--ueb-scale)),
- transparent calc(11px / var(--ueb-scale))),
- repeating-linear-gradient(90deg,
- black,
- black calc(8px / var(--ueb-scale)),
- transparent calc(9px / var(--ueb-scale)),
- transparent calc(11px / var(--ueb-scale))),
- /* Bottom */
- repeating-linear-gradient(90deg,
- transparent,
- transparent calc(1px / var(--ueb-scale)),
- white calc(2px / var(--ueb-scale)),
- white calc(7px / var(--ueb-scale)),
- transparent calc(7px / var(--ueb-scale)),
- transparent calc(11px / var(--ueb-scale))),
- repeating-linear-gradient(90deg,
- black,
- black calc(8px / var(--ueb-scale)),
- transparent calc(9px / var(--ueb-scale)),
- transparent calc(11px / var(--ueb-scale))),
- /* Left */
- repeating-linear-gradient(180deg,
- transparent,
- transparent calc(1px / var(--ueb-scale)),
- white calc(1px / var(--ueb-scale)),
- white calc(7px / var(--ueb-scale)),
- transparent calc(7px / var(--ueb-scale)),
- transparent calc(11px / var(--ueb-scale))),
- repeating-linear-gradient(180deg,
- black,
- black calc(8px / var(--ueb-scale)),
- transparent calc(9px / var(--ueb-scale)),
- transparent calc(11px / var(--ueb-scale))),
- /* Right */
- repeating-linear-gradient(0deg,
- transparent,
- transparent calc(1px / var(--ueb-scale)),
- white calc(2px / var(--ueb-scale)),
- white calc(7px / var(--ueb-scale)),
- transparent calc(7px / var(--ueb-scale)),
- transparent calc(11px / var(--ueb-scale))),
- repeating-linear-gradient(0deg,
- black,
- black calc(8px / var(--ueb-scale)),
- transparent calc(9px / var(--ueb-scale)),
- transparent calc(11px / var(--ueb-scale)));
- background-size:
- /* Top */
- 100% calc(1px / var(--ueb-scale)),
- 100% calc(3px / var(--ueb-scale)),
- /* Bottom */
- 100% calc(1px / var(--ueb-scale)),
- 100% calc(3px / var(--ueb-scale)),
- /* Left */
- calc(1px / var(--ueb-scale)) 100%,
- calc(3px / var(--ueb-scale)) 100%,
- /* Right */
- calc(1px / var(--ueb-scale)) 100%,
- calc(3px / var(--ueb-scale)) 100%;
- background-position:
- /* Top */
- 0 calc(1px / var(--ueb-scale)), 0 0,
- /* Bottom */
- 0 calc(100% - 1px / var(--ueb-scale)), 0 100%,
- /* Left */
- calc(1px / var(--ueb-scale)) 0, 0 0,
- /* Right */
- calc(100% - 1px / var(--ueb-scale)) 0, 100% 0;
- background-repeat: no-repeat;
-}
-
-ueb-selector>* {
- visibility: visible;
-}
-
-ueb-selector[data-selecting="true"] {
- visibility: visible;
- top : min(var(--ueb-select-from-y) * 1px, var(--ueb-select-to-y) * 1px);
- left : min(var(--ueb-select-from-x) * 1px, var(--ueb-select-to-x) * 1px);
- width : calc(max(var(--ueb-select-from-x) - var(--ueb-select-to-x), var(--ueb-select-to-x) - var(--ueb-select-from-x)) * 1px);
- height : calc(max(var(--ueb-select-from-y) - var(--ueb-select-to-y), var(--ueb-select-to-y) - var(--ueb-select-from-y)) * 1px);
+@font-face {
+ font-family: "Roboto";
+ font-style : light;
+ src :
+ url("../font/roboto-light.woff2") format("woff2"),
+ url("../font/roboto-light.woff") format("woff");
+}
+
+@font-face {
+ font-family: "Roboto";
+ font-style : regular;
+ src :
+ url("../font/roboto-regular.woff2") format("woff2"),
+ url("../font/roboto-regular.woff") format("woff");
+}
+
+:root {
+ --ueb-fron-size : 13px;
+ --ueb-viewport-height : 30rem;
+ --ueb-viewport-width : 100%;
+ --ueb-grid-size : 16px;
+ --ueb-grid-line-width : 2px;
+ --ueb-grid-line-color : #353535;
+ --ueb-grid-set : 8;
+ --ueb-grid-set-line-color : #161616;
+ --ueb-grid-axis-line-color: black;
+ --ueb-grid-snap : 16px;
+ --ueb-node-radius : 8px;
+}
+
+ueb-blueprint {
+ display : block;
+ position : relative;
+ font-family: Roboto, Noto, Oxygen, Ubuntu, "Open Sans", "Helvetica Neue", sans-serif;
+ font-size : var(--ueb-fron-size);
+ user-select: none;
+}
+
+.ueb-viewport-header {
+ display : flex;
+ position : absolute;
+ top : 0;
+ right : 0;
+ left : 0;
+ height : 1.5em;
+ background: rgba(0, 0, 0, 0.5);
+ z-index : 1;
+}
+
+.ueb-viewport-zoom {
+ color: #4d4d4db7;
+}
+
+.ueb-viewport-body {
+ position : relative;
+ height : var(--ueb-viewport-height);
+ width : var(--ueb-viewport-width);
+ overflow : hidden;
+ scrollbar-width: 0;
+}
+
+ueb-blueprint[data-focused="true"] .ueb-viewport-body {
+ overflow: scroll;
+}
+
+.ueb-grid {
+ --ueb-grid-line-actual-width: calc(var(--ueb-grid-line-width) / var(--ueb-scale));
+ position : absolute;
+ min-width : 100%;
+ min-height : 100%;
+ width : calc((100% + var(--ueb-additional-x) * 1px) / var(--ueb-scale));
+ height : calc((100% + var(--ueb-additional-y) * 1px) / var(--ueb-scale));
+ background-color : #262626;
+ background-image :
+ /* Axis lines */
+ linear-gradient(var(--ueb-grid-axis-line-color),
+ var(--ueb-grid-axis-line-color)),
+ linear-gradient(var(--ueb-grid-axis-line-color),
+ var(--ueb-grid-axis-line-color)),
+ /* Dark bigger grid */
+ linear-gradient(to right,
+ var(--ueb-grid-set-line-color),
+ var(--ueb-grid-set-line-color) var(--ueb-grid-line-actual-width),
+ transparent var(--ueb-grid-line-actual-width),
+ transparent),
+ linear-gradient(to bottom,
+ var(--ueb-grid-set-line-color),
+ var(--ueb-grid-set-line-color) var(--ueb-grid-line-actual-width),
+ transparent var(--ueb-grid-line-actual-width),
+ transparent),
+ /* Light grid */
+ linear-gradient(to right,
+ var(--ueb-grid-line-color),
+ var(--ueb-grid-line-color) var(--ueb-grid-line-actual-width),
+ transparent var(--ueb-grid-line-actual-width),
+ transparent),
+ linear-gradient(to bottom,
+ var(--ueb-grid-line-color),
+ var(--ueb-grid-line-color) var(--ueb-grid-line-actual-width),
+ transparent var(--ueb-grid-line-actual-width),
+ transparent);
+ background-size:
+ /* Axis lines */
+ 100% var(--ueb-grid-line-actual-width),
+ var(--ueb-grid-line-actual-width) 100%,
+ /* Dark bigger grid */
+ calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)) calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)),
+ calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)) calc(var(--ueb-grid-set) * var(--ueb-grid-actual-size)),
+ /* Light grid */
+ var(--ueb-grid-actual-size) var(--ueb-grid-actual-size),
+ var(--ueb-grid-actual-size) var(--ueb-grid-actual-size);
+ background-position: calc(var(--ueb-translate-x) * 1px) calc(var(--ueb-translate-y) * 1px);
+ background-repeat : repeat-x, repeat-y, repeat, repeat, repeat, repeat;
+ transform : scale(var(--ueb-scale), var(--ueb-scale));
+ transform-origin : 0 0;
+ overflow : hidden;
+}
+
+.ueb-grid[data-drag-scrolling="true"] {
+ cursor: grabbing;
+}
+
+.ueb-zoom--.ueb,
+.ueb {
+ /* 16/16 */
+ --ueb-scale : 1;
+ --ueb-grid-actual-size: var(--ueb-grid-size);
+}
+
+.ueb-zoom--1.ueb {
+ /* 14/16 */
+ --ueb-scale: 0.875;
+}
+
+.ueb-zoom--2.ueb {
+ /* 12/16 */
+ --ueb-scale: 0.75;
+}
+
+.ueb-zoom--3.ueb {
+ /* 10.8/16 */
+ --ueb-scale: 0.675;
+}
+
+.ueb-zoom--4.ueb {
+ /* 8/16 */
+ --ueb-scale : 0.5;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 2);
+}
+
+.ueb-zoom--5.ueb {
+ /* 6/16 */
+ --ueb-scale : 0.375;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 2);
+}
+
+.ueb-zoom--6.ueb {
+ --ueb-scale : 0.333333;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
+}
+
+.ueb-zoom--7.ueb {
+ --ueb-scale : 0.3;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
+}
+
+.ueb-zoom--8.ueb {
+ --ueb-scale : 0.266666;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
+}
+
+.ueb-zoom--9.ueb {
+ --ueb-scale : 0.233333;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
+}
+
+.ueb-zoom--10.ueb {
+ /* 12/16 */
+ --ueb-scale : 0.2;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 3);
+}
+
+.ueb-zoom--11.ueb {
+ /* 12/16 */
+ --ueb-scale : 0.166666;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 6);
+}
+
+.ueb-zoom--12.ueb {
+ /* 12/16 */
+ --ueb-scale : 0.133333;
+ --ueb-grid-actual-size: calc(var(--ueb-grid-size) * 6);
+}
+
+.ueb-grid-content {
+ position : relative;
+ width : 0;
+ height : 0;
+ transform: translateX(calc(var(--ueb-translate-x) * 1px)) translateY(calc(var(--ueb-translate-y) * 1px));
+}
+
+ueb-node {
+ display : block;
+ position : absolute;
+ transform : translateX(calc(var(--ueb-position-x) * 1px)) translateY(calc(var(--ueb-position-y) * 1px));
+ border-radius: var(--ueb-node-radius);
+ box-shadow : 0 0 1px 0 black, 1px 4px 6px 0 rgba(0, 0, 0, 0.3);
+ will-change : transform;
+}
+
+.ueb-grid[data-drag-scrolling="false"] ueb-selector[data-selecting="false"]~ueb-node {
+ cursor: move;
+}
+
+.ueb-node-border {
+ margin : -3px;
+ padding : 3px;
+ border-radius: calc(var(--ueb-node-radius) * 1.4);
+}
+
+.ueb-selected {
+ z-index: 1;
+}
+
+.ueb-selected>.ueb-node-border {
+ background-image:
+ linear-gradient(to right, #f1b000 0%, #f1b000 100%),
+ linear-gradient(to bottom, #f1b000 0%, #cc6700 100%),
+ linear-gradient(to right, #cc6700 0%, #cc6700 100%),
+ linear-gradient(to bottom, #f1b000 0%, #cc6700 100%);
+ background-size : 100% 7px, 7px 100%, 100% 7px, 7px 100%;
+ background-position: top, right, bottom, left;
+ background-repeat : repeat-x, repeat-y, repeat-x, repeat-y;
+ outline : 3px solid #cc6700;
+ outline-offset : -6px;
+}
+
+.ueb-node-content {
+ position : relative;
+ padding : 1px;
+ box-shadow : inset 0 0 2px 0 black;
+ border-radius: var(--ueb-node-radius);
+ background : rgba(0, 0, 0, 0.7);
+ overflow : hidden;
+}
+
+.ueb-node-header {
+ padding : 0.2em 0.7em;
+ box-shadow : inset 0 1px 2px 0 #313631, inset 0 2px 0 0 #92c381;
+ border-radius: var(--ueb-node-radius) var(--ueb-node-radius) 0 0;
+ background : linear-gradient(170deg, #5f815a 0%, #5f815a 50%, transparent 100%);
+ color : #c0c0c0;
+ font-weight : 600;
+ white-space : nowrap;
+}
+
+.ueb-node-name {
+ background: radial-gradient(closest-side, rgba(0, 0, 0, 0.5) 0%, transparent 90%);
+ margin : -0.1em -1.6em;
+ padding : 0.1em 1.6em;
+}
+
+.ueb-node-body {
+ display : flex;
+ padding : 6px 0;
+ color : white;
+ font-weight: 100;
+ white-space: nowrap;
+}
+
+.ueb-node-inputs {
+ margin-right: auto;
+ padding-left: 8px;
+}
+
+.ueb-node-outputs {
+ padding-right: 8px;
+}
+
+ueb-pin {
+ display: block;
+ padding: 1px 2px;
+}
+
+.ueb-grid[data-drag-scrolling="false"] {
+ cursor: default;
+}
+
+ueb-selector[data-selecting="false"]~ueb-node ueb-pin:hover {
+ background: var(--ueb-node-value-background);
+}
+
+.ueb-grid[data-drag-scrolling="false"] ueb-selector[data-selecting="false"]~ueb-node ueb-pin .ueb-node-value-icon {
+ cursor: crosshair;
+}
+
+.ueb-node-value-icon {
+ display : inline-block;
+ position : relative;
+ width : 0.85em;
+ height : 0.85em;
+ vertical-align: baseline;
+ margin : 0 0.4em -1px 0.1em;
+}
+
+.ueb-node-value-icon::before {
+ content : "";
+ display : block;
+ position : absolute;
+ top : 0;
+ right : 0;
+ bottom : 0;
+ left : 0;
+ border : 2px solid var(--ueb-node-value-color);
+ border-radius: 50%;
+}
+
+.ueb-node-value-fill::before {
+ background: var(--ueb-node-value-color);
+}
+
+.ueb-node-value-icon::after {
+ content : "";
+ display : block;
+ position : absolute;
+ top : calc(50% - 0.3em);
+ left : calc(100% + 1px);
+ width : 0;
+ height : 0;
+ border-top : 0.3em solid transparent;
+ border-bottom: 0.3em solid transparent;
+ border-left : 0.3em solid var(--ueb-node-value-color);
+}
+
+.ueb-selector {
+ display : block;
+ position : absolute;
+ visibility: hidden;
+ top : 0;
+ left : 0;
+ width : 0;
+ height : 0;
+ background-image:
+ /* Top */
+ repeating-linear-gradient(90deg,
+ transparent,
+ transparent calc(1px / var(--ueb-scale)),
+ white calc(2px / var(--ueb-scale)),
+ white calc(7px / var(--ueb-scale)),
+ transparent calc(7px / var(--ueb-scale)),
+ transparent calc(11px / var(--ueb-scale))),
+ repeating-linear-gradient(90deg,
+ black,
+ black calc(8px / var(--ueb-scale)),
+ transparent calc(9px / var(--ueb-scale)),
+ transparent calc(11px / var(--ueb-scale))),
+ /* Bottom */
+ repeating-linear-gradient(90deg,
+ transparent,
+ transparent calc(1px / var(--ueb-scale)),
+ white calc(2px / var(--ueb-scale)),
+ white calc(7px / var(--ueb-scale)),
+ transparent calc(7px / var(--ueb-scale)),
+ transparent calc(11px / var(--ueb-scale))),
+ repeating-linear-gradient(90deg,
+ black,
+ black calc(8px / var(--ueb-scale)),
+ transparent calc(9px / var(--ueb-scale)),
+ transparent calc(11px / var(--ueb-scale))),
+ /* Left */
+ repeating-linear-gradient(180deg,
+ transparent,
+ transparent calc(1px / var(--ueb-scale)),
+ white calc(1px / var(--ueb-scale)),
+ white calc(7px / var(--ueb-scale)),
+ transparent calc(7px / var(--ueb-scale)),
+ transparent calc(11px / var(--ueb-scale))),
+ repeating-linear-gradient(180deg,
+ black,
+ black calc(8px / var(--ueb-scale)),
+ transparent calc(9px / var(--ueb-scale)),
+ transparent calc(11px / var(--ueb-scale))),
+ /* Right */
+ repeating-linear-gradient(0deg,
+ transparent,
+ transparent calc(1px / var(--ueb-scale)),
+ white calc(2px / var(--ueb-scale)),
+ white calc(7px / var(--ueb-scale)),
+ transparent calc(7px / var(--ueb-scale)),
+ transparent calc(11px / var(--ueb-scale))),
+ repeating-linear-gradient(0deg,
+ black,
+ black calc(8px / var(--ueb-scale)),
+ transparent calc(9px / var(--ueb-scale)),
+ transparent calc(11px / var(--ueb-scale)));
+ background-size:
+ /* Top */
+ 100% calc(1px / var(--ueb-scale)),
+ 100% calc(3px / var(--ueb-scale)),
+ /* Bottom */
+ 100% calc(1px / var(--ueb-scale)),
+ 100% calc(3px / var(--ueb-scale)),
+ /* Left */
+ calc(1px / var(--ueb-scale)) 100%,
+ calc(3px / var(--ueb-scale)) 100%,
+ /* Right */
+ calc(1px / var(--ueb-scale)) 100%,
+ calc(3px / var(--ueb-scale)) 100%;
+ background-position:
+ /* Top */
+ 0 calc(1px / var(--ueb-scale)), 0 0,
+ /* Bottom */
+ 0 calc(100% - 1px / var(--ueb-scale)), 0 100%,
+ /* Left */
+ calc(1px / var(--ueb-scale)) 0, 0 0,
+ /* Right */
+ calc(100% - 1px / var(--ueb-scale)) 0, 100% 0;
+ background-repeat: no-repeat;
+}
+
+ueb-selector>* {
+ visibility: visible;
+}
+
+ueb-selector[data-selecting="true"] {
+ visibility: visible;
+ top : min(var(--ueb-select-from-y) * 1px, var(--ueb-select-to-y) * 1px);
+ left : min(var(--ueb-select-from-x) * 1px, var(--ueb-select-to-x) * 1px);
+ width : calc(max(var(--ueb-select-from-x) - var(--ueb-select-to-x), var(--ueb-select-to-x) - var(--ueb-select-from-x)) * 1px);
+ height : calc(max(var(--ueb-select-from-y) - var(--ueb-select-to-y), var(--ueb-select-to-y) - var(--ueb-select-from-y)) * 1px);
}
\ No newline at end of file