Files
Superalgos/DesignerSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js
T

265 lines
9.5 KiB
JavaScript

function newUiObjectsFromNodes () {
thisObject = {
recreateWorkspace: recreateWorkspace,
tryToConnectChildrenWithReferenceParents: tryToConnectChildrenWithReferenceParents,
createUiObjectFromNode: createUiObjectFromNode,
addUIObject: addUIObject,
addMissingChildren: addMissingChildren
}
let mapOfReferenceChildren = new Map()
let mapOfNodes
return thisObject
function recreateWorkspace (node) {
mapOfNodes = new Map()
/* Create the workspace UI OBject and then continue with the root nodes. */
createUiObject(false, 'Workspace', node.name, node, undefined, undefined, 'Workspace')
if (node.rootNodes !== undefined) {
for (let i = 0; i < node.rootNodes.length; i++) {
let rootNode = node.rootNodes[i]
createUiObjectFromNode(rootNode, undefined, undefined)
}
}
tryToConnectChildrenWithReferenceParents()
}
function tryToConnectChildrenWithReferenceParents () {
/* We reconstruct here the reference relationships. */
for (const [key, node] of mapOfNodes) {
if (node.payload === undefined) { continue }
if (node.payload.referenceParent !== undefined) {
if (node.payload.referenceParent.cleaned === true) {
node.payload.referenceParent = mapOfNodes.get(node.payload.referenceParent.id)
continue // We were referencing a deleted node, so we replace it potentially with a newly created one.
} else {
continue // In this case the reference is already good.
}
}
if (node.savedPayload !== undefined) {
if (node.savedPayload.referenceParent !== undefined) { // these are children recreated
node.payload.referenceParent = mapOfNodes.get(node.savedPayload.referenceParent.id)
}
}
}
}
function createUiObjectFromNode (node, parentNode, chainParent, positionOffset) {
/* Get node definition */
let nodeDefinition = APP_SCHEMA_MAP.get(node.type)
if (nodeDefinition !== undefined) {
/* Resolve Initial Values */
if (nodeDefinition.initialValues !== undefined) {
if (nodeDefinition.initialValues.code !== undefined) {
if (node.code === undefined) {
node.code = nodeDefinition.initialValues.code
}
}
}
/* Create Self */
createUiObject(false, node.type, node.name, node, parentNode, chainParent, node.type, positionOffset)
/* Create Children */
if (nodeDefinition.properties !== undefined) {
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
for (let i = 0; i < nodeDefinition.properties.length; i++) {
let property = nodeDefinition.properties[i]
if (node[property.name] !== undefined) {
switch (property.type) {
case 'node': {
if (property.name !== previousPropertyName) {
createUiObjectFromNode(node[property.name], node, node, positionOffset)
previousPropertyName = property.name
}
}
break
case 'array': {
let nodePropertyArray = node[property.name]
for (let m = 0; m < nodePropertyArray.length; m++) {
let arrayItem = nodePropertyArray[m]
createUiObjectFromNode(arrayItem, node, node, positionOffset)
}
}
break
}
}
}
}
}
}
function addUIObject (parent, type) {
let object = {
name: 'New ' + type,
type: type
}
let parentNodeDefinition = APP_SCHEMA_MAP.get(parent.type)
if (parentNodeDefinition !== undefined) {
/* Resolve Initial Values */
let nodeDefinition = APP_SCHEMA_MAP.get(object.type)
if (nodeDefinition.isHierarchyHead === true) {
parent.rootNodes.push(object)
createUiObject(true, object.type, object.name, object, parent, undefined)
return object
}
createUiObject(true, object.type, object.name, object, parent, parent)
if (nodeDefinition !== undefined) {
if (nodeDefinition.initialValues !== undefined) {
if (nodeDefinition.initialValues.code !== undefined) {
object.code = nodeDefinition.initialValues.code
}
}
}
/* Connect to Parent */
if (parentNodeDefinition.properties !== undefined) {
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
for (let i = 0; i < parentNodeDefinition.properties.length; i++) {
let property = parentNodeDefinition.properties[i]
if (property.childType === type) {
switch (property.type) {
case 'node': {
if (property.name !== previousPropertyName) {
parent[property.name] = object
previousPropertyName = property.name
}
}
break
case 'array': {
if (parent[property.name] === undefined) {
parent[property.name] = []
}
parent[property.name].push(object)
}
break
}
}
}
}
}
return object
}
function addMissingChildren (node) {
}
function createUiObject (userAddingNew, uiObjectType, name, node, parentNode, chainParent, title, positionOffset) {
let payload = {}
/* Mechanism related to keeping references when cloning */
if (node.id === undefined) {
node.id = newUniqueId()
} else {
let testNode = mapOfNodes.get(node.id)
if (testNode !== undefined && testNode.cleaned !== true) {
node.id = newUniqueId()
}
}
/* Default Naming */
if (name === '' || name === undefined) { name = 'My ' + uiObjectType }
/* If we are creating this object as the result of restoring a backup, share or clone, we will bring some of the saved properties to the new running instance. */
if (userAddingNew === false && uiObjectType !== 'Workspace') {
/* This following info can not be missing. */
if (node.savedPayload === undefined) {
console.log('Node ' + node.type + ' without savedPayload.', node)
return
}
if (node.savedPayload.position === undefined) {
console.log('Node ' + node.type + ' without savedPayload.position.', node)
return
}
if (node.savedPayload.targetPosition === undefined) {
console.log('Node ' + node.type + ' without savedPayload.targetPosition.', node)
return
}
/* If there is not a position offset, which happens when we are dropping a node into the designer, we create a cero vector then. */
if (positionOffset === undefined) {
positionOffset = {
x: 0,
y: 0
}
}
/* Adding the offset to the saved positions. */
node.savedPayload.targetPosition.x = node.savedPayload.targetPosition.x + positionOffset.x
node.savedPayload.targetPosition.y = node.savedPayload.targetPosition.y + positionOffset.y
node.savedPayload.position.x = node.savedPayload.position.x + positionOffset.x
node.savedPayload.position.y = node.savedPayload.position.y + positionOffset.y
/* Transferring the saved payload properties into the running instance being created. */
payload.targetPosition = {
x: node.savedPayload.targetPosition.x,
y: node.savedPayload.targetPosition.y
}
node.savedPayload.targetPosition = undefined
/* Reference children connection to parents */
if (node.savedPayload.referenceParent !== undefined) {
payload.referenceParent = mapOfNodes.get(node.savedPayload.referenceParent.id)
if (payload.referenceParent !== undefined) {
mapOfReferenceChildren.set(node.id, node)
}
}
}
/* If we are adding a new object, then we set the initial values for position and targetPosition */
if (userAddingNew === true || uiObjectType === 'Workspace') {
/* Workspace allways to the spawn position */
if (uiObjectType === 'Workspace') {
payload.position = {
x: spawnPosition.x,
y: spawnPosition.y
}
}
/* Chain parent pointing to the position of the chain parent if defined. */
if (chainParent === undefined) {
payload.targetPosition = {
x: spawnPosition.x,
y: spawnPosition.y
}
} else {
payload.targetPosition = {
x: chainParent.payload.position.x,
y: chainParent.payload.position.y
}
}
}
/* Setting the title */
if (title !== undefined) {
payload.subTitle = title
} else {
payload.subTitle = uiObjectType
}
payload.visible = true
payload.title = name
payload.node = node
payload.parentNode = parentNode
payload.chainParent = chainParent
payload.onMenuItemClick = canvas.designerSpace.workspace.onMenuItemClick
node.payload = payload
node.type = uiObjectType
/* Now we mount the floating object where the UIOBject will be laying on top of */
canvas.floatingSpace.uiObjectConstructor.createUiObject(userAddingNew, payload)
mapOfNodes.set(node.id, node)
}
}