diff --git a/dist/ueblueprint.js b/dist/ueblueprint.js index fad0149..6d77425 100755 --- a/dist/ueblueprint.js +++ b/dist/ueblueprint.js @@ -219,6 +219,32 @@ class IInput { */ class TypeInitialization { + /** @type {T} */ + #value + get value() { + return this.#value + } + set value(v) { + this.#value = v; + } + + #showDefault = true + get showDefault() { + return this.#showDefault + } + set showDefault(v) { + this.#showDefault = v; + } + + /** @type {Constructor|Array} */ + #type + get type() { + return this.#type + } + set type(v) { + this.#type = v; + } + static sanitize(value, targetType) { if (targetType === undefined) { targetType = value?.constructor; @@ -237,17 +263,22 @@ class TypeInitialization { } /** - * @param {new () => T} type + * @typedef {new () => T} Constructor + * @param {Constructor|Array} type * @param {Boolean} showDefault * @param {any} value */ constructor(type, showDefault = true, value = undefined) { if (value === undefined) { - value = TypeInitialization.sanitize(new type()); + if (type instanceof Array) { + value = []; + } else { + value = TypeInitialization.sanitize(new type()); + } } - this.value = value; - this.showDefault = showDefault; - this.type = type; + this.#value = value; + this.#showDefault = showDefault; + this.#type = type; } } @@ -334,7 +365,12 @@ class Utility { static equals(a, b) { a = TypeInitialization.sanitize(a); b = TypeInitialization.sanitize(b); - return a === b + if (a === b) { + return true + } + if (a instanceof Array && b instanceof Array) { + return a.length == b.length && !a.find((value, i) => !Utility.equals(value, b[i])) + } } /** @@ -348,8 +384,9 @@ class Utility { let constructor = value?.constructor; switch (constructor) { case TypeInitialization: - return value.type + return Utility.getType(value.type) case Function: + // value is already a constructor return value default: return constructor @@ -398,7 +435,14 @@ class Utility { return value .replace(/\n$/, "") // Remove trailing newline .replaceAll("\u00A0", " ") // Replace special space symbol - .replaceAll("\n", "\\r\\n") // Replace newline with \r\n + .replaceAll("\n", String.raw`\r\n`) // Replace newline with \r\n + } + + /** + * @param {String} value + */ + static formatStringName(value) { + return value.replaceAll(/\s+/g, " ").replaceAll(/(?<=[a-z])(?=[A-Z])|_/g, " ").trim() } } @@ -424,11 +468,7 @@ class IEntity { console.warn(`Property ${prefix}${property} is not defined in ${this.constructor.name}`); } let defaultValue = properties[property]; - const defaultType = (defaultValue instanceof TypeInitialization) - ? defaultValue.type - : (defaultValue instanceof Function) - ? defaultValue - : defaultValue?.constructor; + const defaultType = Utility.getType(defaultValue); // Not instanceof because all objects are instenceof Object, exact match needed if (defaultType === Object) { target[property] = {}; @@ -708,8 +748,8 @@ class PinEntity extends IEntity { bIsWeakPointer: false, bIsUObjectWrapper: false, }, - LinkedTo: [PinReferenceEntity], - DefaultValue: "", + LinkedTo: new TypeInitialization([PinReferenceEntity], false), + DefaultValue: new TypeInitialization(String, false), AutogeneratedDefaultValue: "", DefaultObject: new TypeInitialization(ObjectReferenceEntity, false, null), PersistentGuid: GuidEntity, @@ -897,7 +937,13 @@ class ObjectEntity extends IEntity { } getDisplayName() { - return this.getNameAndCounter()[0] + let name = this.FunctionReference?.MemberName; + if (name) { + name = Utility.formatStringName(name); + return name + } + name = Utility.formatStringName(this.getNameAndCounter()[0]); + return name } getCounter() { @@ -928,6 +974,9 @@ class Grammar { /* --- Factory --- */ static getGrammarForType(r, attributeType, defaultGrammar) { + if (attributeType instanceof TypeInitialization) { + attributeType = attributeType.type; + } switch (Utility.getType(attributeType)) { case Boolean: return r.Boolean @@ -3213,7 +3262,7 @@ class NodeTemplate extends SelectableDraggableTemplate {
- ${sanitizeText(node.getNodeName())} + ${sanitizeText(node.getNodeDisplayName())}
@@ -3309,6 +3358,10 @@ class NodeElement extends ISelectableDraggableElement { return this.entity.getFullName() } + getNodeDisplayName() { + return this.entity.getDisplayName() + } + sanitizeLinks() { this.getPinElements().forEach(pin => pin.sanitizeLinks()); } diff --git a/js/Utility.js b/js/Utility.js index 2a72ea7..04afa3a 100755 --- a/js/Utility.js +++ b/js/Utility.js @@ -83,7 +83,12 @@ export default class Utility { static equals(a, b) { a = TypeInitialization.sanitize(a) b = TypeInitialization.sanitize(b) - return a === b + if (a === b) { + return true + } + if (a instanceof Array && b instanceof Array) { + return a.length == b.length && !a.find((value, i) => !Utility.equals(value, b[i])) + } } /** @@ -97,8 +102,9 @@ export default class Utility { let constructor = value?.constructor switch (constructor) { case TypeInitialization: - return value.type + return Utility.getType(value.type) case Function: + // value is already a constructor return value default: return constructor @@ -147,6 +153,13 @@ export default class Utility { return value .replace(/\n$/, "") // Remove trailing newline .replaceAll("\u00A0", " ") // Replace special space symbol - .replaceAll("\n", "\\r\\n") // Replace newline with \r\n + .replaceAll("\n", String.raw`\r\n`) // Replace newline with \r\n + } + + /** + * @param {String} value + */ + static formatStringName(value) { + return value.replaceAll(/\s+/g, " ").replaceAll(/(?<=[a-z])(?=[A-Z])|_/g, " ").trim() } } diff --git a/js/element/NodeElement.js b/js/element/NodeElement.js index d3318be..bb6007a 100644 --- a/js/element/NodeElement.js +++ b/js/element/NodeElement.js @@ -41,6 +41,10 @@ export default class NodeElement extends ISelectableDraggableElement { return this.entity.getFullName() } + getNodeDisplayName() { + return this.entity.getDisplayName() + } + sanitizeLinks() { this.getPinElements().forEach(pin => pin.sanitizeLinks()) } diff --git a/js/entity/IEntity.js b/js/entity/IEntity.js index 8117b39..8824937 100644 --- a/js/entity/IEntity.js +++ b/js/entity/IEntity.js @@ -23,11 +23,7 @@ export default class IEntity { console.warn(`Property ${prefix}${property} is not defined in ${this.constructor.name}`) } let defaultValue = properties[property] - const defaultType = (defaultValue instanceof TypeInitialization) - ? defaultValue.type - : (defaultValue instanceof Function) - ? defaultValue - : defaultValue?.constructor + const defaultType = Utility.getType(defaultValue) // Not instanceof because all objects are instenceof Object, exact match needed if (defaultType === Object) { target[property] = {} diff --git a/js/entity/ObjectEntity.js b/js/entity/ObjectEntity.js index 4c4afcb..7ad7574 100755 --- a/js/entity/ObjectEntity.js +++ b/js/entity/ObjectEntity.js @@ -1,5 +1,6 @@ // @ts-check +import Utility from "../Utility" import FunctionReferenceEntity from "./FunctionReferenceEntity" import GuidEntity from "./GuidEntity" import IdentifierEntity from "./IdentifierEntity" @@ -66,7 +67,13 @@ export default class ObjectEntity extends IEntity { } getDisplayName() { - return this.getNameAndCounter()[0] + let name = this.FunctionReference?.MemberName + if (name) { + name = Utility.formatStringName(name) + return name + } + name = Utility.formatStringName(this.getNameAndCounter()[0]) + return name } getCounter() { diff --git a/js/entity/PinEntity.js b/js/entity/PinEntity.js index 99afe86..b3afdff 100755 --- a/js/entity/PinEntity.js +++ b/js/entity/PinEntity.js @@ -28,8 +28,8 @@ export default class PinEntity extends IEntity { bIsWeakPointer: false, bIsUObjectWrapper: false, }, - LinkedTo: [PinReferenceEntity], - DefaultValue: "", + LinkedTo: new TypeInitialization([PinReferenceEntity], false), + DefaultValue: new TypeInitialization(String, false), AutogeneratedDefaultValue: "", DefaultObject: new TypeInitialization(ObjectReferenceEntity, false, null), PersistentGuid: GuidEntity, diff --git a/js/entity/TypeInitialization.js b/js/entity/TypeInitialization.js index 48dae52..3fa7be4 100755 --- a/js/entity/TypeInitialization.js +++ b/js/entity/TypeInitialization.js @@ -5,6 +5,32 @@ */ export default class TypeInitialization { + /** @type {T} */ + #value + get value() { + return this.#value + } + set value(v) { + this.#value = v + } + + #showDefault = true + get showDefault() { + return this.#showDefault + } + set showDefault(v) { + this.#showDefault = v + } + + /** @type {Constructor|Array} */ + #type + get type() { + return this.#type + } + set type(v) { + this.#type = v + } + static sanitize(value, targetType) { if (targetType === undefined) { targetType = value?.constructor @@ -23,16 +49,21 @@ export default class TypeInitialization { } /** - * @param {new () => T} type + * @typedef {new () => T} Constructor + * @param {Constructor|Array} type * @param {Boolean} showDefault * @param {any} value */ constructor(type, showDefault = true, value = undefined) { if (value === undefined) { - value = TypeInitialization.sanitize(new type()) + if (type instanceof Array) { + value = [] + } else { + value = TypeInitialization.sanitize(new type()) + } } - this.value = value - this.showDefault = showDefault - this.type = type + this.#value = value + this.#showDefault = showDefault + this.#type = type } } diff --git a/js/serialization/Grammar.js b/js/serialization/Grammar.js index d7d2a45..94d1339 100755 --- a/js/serialization/Grammar.js +++ b/js/serialization/Grammar.js @@ -13,6 +13,7 @@ import Parsimmon from "parsimmon" import PathSymbolEntity from "../entity/PathSymbolEntity" import PinEntity from "../entity/PinEntity" import PinReferenceEntity from "../entity/PinReferenceEntity" +import TypeInitialization from "../entity/TypeInitialization" import Utility from "../Utility" let P = Parsimmon @@ -22,6 +23,9 @@ export default class Grammar { /* --- Factory --- */ static getGrammarForType(r, attributeType, defaultGrammar) { + if (attributeType instanceof TypeInitialization) { + attributeType = attributeType.type + } switch (Utility.getType(attributeType)) { case Boolean: return r.Boolean diff --git a/js/template/NodeTemplate.js b/js/template/NodeTemplate.js index 3079f27..7739b7f 100755 --- a/js/template/NodeTemplate.js +++ b/js/template/NodeTemplate.js @@ -24,7 +24,7 @@ export default class NodeTemplate extends SelectableDraggableTemplate {
- ${sanitizeText(node.getNodeName())} + ${sanitizeText(node.getNodeDisplayName())}