Files
Superalgos/Projects/Foundations/UI/Spaces/Floating-Space/UiObject.js
T

2484 lines
102 KiB
JavaScript

function newUiObject() {
const MODULE_NAME = 'UI Object'
const ERROR_LOG = true
const logger = newWebDebugLog()
let thisObject = {
fitFunction: undefined,
isVisibleFunction: undefined,
type: undefined,
menu: undefined,
isOnFocus: false,
container: undefined,
payload: undefined,
codeEditor: undefined,
configEditor: undefined,
conditionEditor: undefined,
formulaEditor: undefined,
uiObjectTitle: undefined,
uiObjectMessage: undefined,
circularProgressBar: undefined,
isLoading: undefined,
isRunning: undefined,
isPlaying: undefined,
shortcutKey: undefined,
isShowing: undefined,
hasError: undefined,
hasWarning: undefined,
hasInfo: undefined,
valueAtAngle: false,
valueAngleOffset: 0,
percentageAtAngle: false,
percentageAngleOffset: 0,
statusAtAngle: false,
statusAngleOffset: 0,
run: run,
stop: stop,
heartBeat: heartBeat,
getReadyToChainAttach: getReadyToChainAttach,
showAvailabilityToChainAttach: showAvailabilityToChainAttach,
getReadyToReferenceAttach: getReadyToReferenceAttach,
showAvailabilityToReferenceAttach: showAvailabilityToReferenceAttach,
highlight: highlight,
runningAtBackend: runningAtBackend,
reset: reset,
setErrorMessage: setErrorMessage,
resetErrorMessage: resetErrorMessage,
setWarningMessage: setWarningMessage,
resetWarningMessage: resetWarningMessage,
setInfoMessage: setInfoMessage,
resetInfoMessage: resetInfoMessage,
getValue: getValue,
setValue: setValue,
resetValue: resetValue,
setPercentage: setPercentage,
resetPercentage: resetPercentage,
setStatus: setStatus,
resetStatus: resetStatus,
physics: physics,
invisiblePhysics: invisiblePhysics,
drawBackground: drawBackground,
drawMiddleground: drawMiddleground,
drawForeground: drawForeground,
drawOnFocus: drawOnFocus,
getContainer: getContainer,
finalize: finalize,
initialize: initialize
}
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME, 'Circle')
thisObject.container.isClickeable = false
thisObject.container.isDraggeable = false
thisObject.container.frame.radius = 0
thisObject.container.frame.position.x = 0
thisObject.container.frame.position.y = 0
let icon
let executingIcon
let selfFocusEventSubscriptionId
let selfNotFocusEventSubscriptionId
let selfDisplaceEventSubscriptionId
let selfDragStartedEventSubscriptionId
let selfDragFinishedEventSubscriptionId
let isHighlighted
let highlightCounter = 0
let isRunningAtBackend
let runningAtBackendCounter = 0
let errorMessageCounter = 0
let warningMessageCounter = 0
let infoMessageCounter = 0
let hasValue
let valueCounter = 0
let hasPercentage
let percentageCounter = 0
let hasStatus
let statusCounter = 0
let previousDistanceToChainParent
let readyToChainAttachDisplayCounter = 5
let readyToChainAttachDisplayIncrement = 0.1
let readyToChainAttachCounter = 0
let isReadyToChainAttach
let availableToChainAttachCounter = 0
let isAvailableToChainAttach
let isChainAttaching = false
let chainAttachToNode
let previousDistanceToReferenceParent
let readyToReferenceAttachDisplayCounter = 5
let readyToReferenceAttachDisplayIncrement = 0.1
let readyToReferenceAttachCounter = 0
let isReadyToReferenceAttach
let availableToReferenceAttachCounter = 0
let isAvailableToReferenceAttach
let isReferenceAttaching = false
let referenceAttachToNode
let isDragging = false
let errorMessage = ''
let warningMessage = ''
let infoMessage = ''
let errorDocs = undefined
let warningDocs = undefined
let infoDocs = undefined
let currentValue = 0
let valueMinDecimals = undefined
let currentPercentage = ''
let currentStatus = ''
let rightDragging = false
let eventSubscriptionIdOnError
let eventSubscriptionIdOnWarning
let eventSubscriptionIdOnInfo
let eventSubscriptionIdOnRunning
let eventSubscriptionIdOnStopped
let lastHeartBeat
let onRunningCallBackFunction
let onRunningCallBackFunctionWasCalled = false
let newUiObjectCounter = 25
let referenceLineCounter = 0
let chainLineCounter = 0
let eventsServerClient
let errorRingAnimation = 0
let warningRingAnimation = 0
let infoRingAnimation = 0
let errorRingDirectionAnimation = 1
let warningRingDirectionAnimation = 1
let infoRingDirectionAnimation = 1
thisObject.isRunning = false
return thisObject
function finalize() {
finalizeEventsServerClient()
thisObject.container.eventHandler.stopListening(selfFocusEventSubscriptionId)
thisObject.container.eventHandler.stopListening(selfNotFocusEventSubscriptionId)
thisObject.container.eventHandler.stopListening(selfDisplaceEventSubscriptionId)
thisObject.container.eventHandler.stopListening(selfDragStartedEventSubscriptionId)
thisObject.container.eventHandler.stopListening(selfDragFinishedEventSubscriptionId)
thisObject.container.finalize()
thisObject.container = undefined
thisObject.payload = undefined
thisObject.menu.finalize()
thisObject.menu = undefined
thisObject.uiObjectTitle.finalize()
thisObject.uiObjectTitle = undefined
thisObject.uiObjectMessage.finalize()
thisObject.uiObjectMessage = undefined
thisObject.fitFunction = undefined
thisObject.isVisibleFunction = undefined
if (thisObject.codeEditor !== undefined) {
thisObject.codeEditor.finalize()
thisObject.codeEditor = undefined
}
if (thisObject.configEditor !== undefined) {
thisObject.configEditor.finalize()
thisObject.configEditor = undefined
}
if (thisObject.conditionEditor !== undefined) {
thisObject.conditionEditor.finalize()
thisObject.conditionEditor = undefined
}
if (thisObject.formulaEditor !== undefined) {
thisObject.formulaEditor.finalize()
thisObject.formulaEditor = undefined
}
icon = undefined
chainAttachToNode = undefined
referenceAttachToNode = undefined
lastHeartBeat = undefined
onRunningCallBackFunction = undefined
errorDocs = undefined
warningDocs = undefined
infoDocs = undefined
}
function finalizeEventsServerClient() {
if (eventsServerClient !== undefined) {
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
if (eventSubscriptionIdOnRunning !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnRunning, 'UiObject')
}
if (eventSubscriptionIdOnStopped !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnStopped, 'UiObject')
}
if (eventSubscriptionIdOnError !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnError, 'UiObject')
}
if (eventSubscriptionIdOnWarning !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnWarning, 'UiObject')
}
if (eventSubscriptionIdOnInfo !== undefined) {
eventsServerClient.stopListening(key, eventSubscriptionIdOnInfo, 'UiObject')
}
}
}
function initialize(payload, menuItemsInitialValues) {
thisObject.payload = payload
/* Initialize the Menu */
thisObject.menu = newCircularMenu()
thisObject.menu.initialize(menuItemsInitialValues, thisObject.payload)
thisObject.menu.container.connectToParent(thisObject.container, false, false, true, true, false, false, true, true)
/* Initialize UI Object Title */
thisObject.uiObjectTitle = newUiObjectTitle()
thisObject.uiObjectTitle.isVisibleFunction = thisObject.isVisibleFunction
thisObject.uiObjectTitle.container.connectToParent(thisObject.container, false, false, true, true, false, false, true, true)
thisObject.uiObjectTitle.fitFunction = thisObject.fitFunction
thisObject.uiObjectTitle.initialize(thisObject.payload)
/* Initialize UI Object Message */
thisObject.uiObjectMessage = newUiObjectMessage()
thisObject.uiObjectMessage.isVisibleFunction = thisObject.isVisibleFunction
thisObject.uiObjectMessage.container.connectToParent(thisObject.container, false, false, true, true, false, false, false, true)
thisObject.uiObjectMessage.fitFunction = thisObject.fitFunction
thisObject.uiObjectMessage.initialize(thisObject.payload)
/* Load UI Object Image */
iconPhysics()
selfFocusEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onFocus', onFocus)
selfNotFocusEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onNotFocus', onNotFocus)
selfDisplaceEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDisplace', onDisplace)
selfDragStartedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDragStarted', onDragStarted)
selfDragFinishedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDragFinished', onDragFinished)
}
function getContainer(point) {
let container
if (isDragging === false && thisObject.isOnFocus === true) {
if (thisObject.codeEditor !== undefined) {
container = thisObject.codeEditor.getContainer(point)
if (container !== undefined) { return container }
}
if (thisObject.configEditor !== undefined) {
container = thisObject.configEditor.getContainer(point)
if (container !== undefined) { return container }
}
if (thisObject.conditionEditor !== undefined) {
container = thisObject.conditionEditor.getContainer(point)
if (container !== undefined) { return container }
}
if (thisObject.formulaEditor !== undefined) {
container = thisObject.formulaEditor.getContainer(point)
if (container !== undefined) { return container }
}
let getitle = true
if (thisObject.codeEditor !== undefined) {
if (thisObject.codeEditor.visible === true) {
getitle = false
}
}
if (thisObject.configEditor !== undefined) {
if (thisObject.configEditor.visible === true) {
getitle = false
}
}
if (thisObject.conditionEditor !== undefined) {
if (thisObject.conditionEditor.visible === true) {
getitle = false
}
}
if (thisObject.formulaEditor !== undefined) {
if (thisObject.formulaEditor.visible === true) {
getitle = false
}
}
if (getitle === true) {
container = thisObject.uiObjectTitle.getContainer(point)
if (container !== undefined) { return container }
}
container = thisObject.uiObjectMessage.getContainer(point)
if (container !== undefined) { return container }
container = thisObject.menu.getContainer(point)
if (container !== undefined) { return container }
}
if (thisObject.container.frame.isThisPointHere(point, true, true) === true) {
return thisObject.container
} else {
return undefined
}
}
function invisiblePhysics() {
thisObject.menu.invisiblePhysics()
childrenRunningPhysics()
thisObject.uiObjectTitle.physics()
thisObject.uiObjectMessage.physics()
}
function physics() {
thisObject.menu.physics()
thisObject.uiObjectTitle.physics()
thisObject.menu.physics()
thisObject.uiObjectMessage.physics()
if (thisObject.codeEditor !== undefined) {
thisObject.codeEditor.physics()
}
if (thisObject.configEditor !== undefined) {
thisObject.configEditor.physics()
}
if (thisObject.conditionEditor !== undefined) {
thisObject.conditionEditor.physics()
}
if (thisObject.formulaEditor !== undefined) {
thisObject.formulaEditor.physics()
}
if (thisObject.payload.chainParent === undefined || thisObject.payload.chainParent.payload === undefined) {
thisObject.payload.targetPosition.x = thisObject.payload.position.x,
thisObject.payload.targetPosition.y = thisObject.payload.position.y
} else {
if (thisObject.payload.chainParent.payload.position !== undefined) {
thisObject.payload.targetPosition.x = thisObject.payload.chainParent.payload.position.x
thisObject.payload.targetPosition.y = thisObject.payload.chainParent.payload.position.y
}
}
if (thisObject.circularProgressBar !== undefined) {
thisObject.circularProgressBar.physics()
}
iconPhysics()
highlightPhisycs()
runningAtBackendPhisycs()
errorMessagePhisycs()
warningMessagePhisycs()
infoMessagePhisycs()
valuePhisycs()
percentagePhisycs()
statusPhisycs()
chainDetachingPhysics()
chainAttachingPhysics()
referenceDetachingPhysics()
referenceAttachingPhysics()
childrenRunningPhysics()
newObjectPhysics()
referenceLinePhysics()
chainLinePhysics()
ringsAnimationPhysics()
function ringsAnimationPhysics() {
errorRingAnimation = errorRingAnimation + errorRingDirectionAnimation
warningRingAnimation = warningRingAnimation + warningRingDirectionAnimation
infoRingAnimation = infoRingAnimation + infoRingDirectionAnimation
if (errorRingAnimation === 10) { errorRingDirectionAnimation = -1 }
if (warningRingAnimation === 10) { warningRingDirectionAnimation = -1 }
if (infoRingAnimation === 10) { infoRingDirectionAnimation = -1 }
if (errorRingAnimation === 0) { errorRingDirectionAnimation = 1 }
if (warningRingAnimation === 0) { warningRingDirectionAnimation = 1 }
if (infoRingAnimation === 0) { infoRingDirectionAnimation = 1 }
}
function referenceLinePhysics() {
referenceLineCounter = referenceLineCounter + 2
if (referenceLineCounter > 500) {
referenceLineCounter = 0
}
}
function chainLinePhysics() {
chainLineCounter = chainLineCounter - 5
if (chainLineCounter < 0) {
chainLineCounter = 500
}
}
function newObjectPhysics() {
newUiObjectCounter--
if (newUiObjectCounter < 0) {
newUiObjectCounter = 0
}
}
function chainAttachingPhysics() {
chainAttacchingCounters()
if (thisObject.isOnFocus !== true) { return }
if (isDragging !== true) { return }
if (rightDragging !== true) { return }
if (thisObject.payload.chainParent !== undefined) { return }
UI.projects.foundations.spaces.floatingSpace.floatingLayer.isProximityPhysicsNeeded = true
let nearbyFloatingObjects = thisObject.payload.floatingObject.nearbyFloatingObjects
let compatibleTypes
let schemaDocument = getSchemaDocument(thisObject.payload.node)
if (schemaDocument !== undefined) {
if (schemaDocument.attachingRules !== undefined) {
compatibleTypes = schemaDocument.attachingRules.compatibleTypes
} else {
return
}
} else {
return
}
let foundCompatible = false
chainAttachToNode = undefined
isChainAttaching = false
for (let i = 0; i < nearbyFloatingObjects.length; i++) {
let nearby = nearbyFloatingObjects[i]
let distance = nearby[0]
let floatingObject = nearby[1]
if (floatingObject.payload === undefined) { continue }
let nearbyNode = floatingObject.payload.node
if (compatibleTypes.indexOf('->' + nearbyNode.type + '->') >= 0) {
/* Discard App Schema defined objects with busy coonection ports */
schemaDocument = getSchemaDocument(thisObject.payload.node)
if (schemaDocument !== undefined) {
let mustContinue = false
let parentSchemaDocument = getSchemaDocument(nearbyNode)
if (parentSchemaDocument !== undefined) {
if (parentSchemaDocument.childrenNodesProperties !== undefined) {
for (let j = 0; j < parentSchemaDocument.childrenNodesProperties.length; j++) {
let property = parentSchemaDocument.childrenNodesProperties[j]
if (schemaDocument.propertyNameAtParent === property.name) {
switch (property.type) {
case 'node': {
if (nearbyNode[property.name] !== undefined) {
mustContinue = true
}
}
break
case 'array': {
/* Nothing to worry about since an array can take more than one element. */
}
break
}
}
}
}
}
if (mustContinue === true) { continue }
}
/* Discard Phases without partent */
if (thisObject.payload.node.type === 'Phase' && nearbyNode.type === 'Phase' && nearbyNode.payload.parentNode === undefined) { continue }
/* Control maxPhases */
if (thisObject.payload.node.type === 'Phase') {
if (nearbyNode.maxPhases !== undefined) {
if (nearbyNode.phases.length >= nearbyNode.maxPhases) {
continue
}
}
}
if (thisObject.payload.node.type === 'Phase' && nearbyNode.type === 'Phase') {
if (nearbyNode.payload.parentNode.maxPhases !== undefined) {
if (nearbyNode.payload.parentNode.phases.length >= nearbyNode.payload.parentNode.maxPhases) {
continue
}
}
}
if (foundCompatible === false) {
if (distance < thisObject.payload.floatingObject.container.frame.radius * 1.5 + floatingObject.container.frame.radius * 1.5) {
nearbyNode.payload.uiObject.getReadyToChainAttach()
isChainAttaching = true
chainAttachToNode = nearbyNode
foundCompatible = true
}
}
nearbyNode.payload.uiObject.showAvailabilityToChainAttach()
}
}
function chainAttacchingCounters() {
if (readyToChainAttachDisplayCounter > 15) {
readyToChainAttachDisplayIncrement = -0.25
}
if (readyToChainAttachDisplayCounter < 5) {
readyToChainAttachDisplayIncrement = 0.25
}
readyToChainAttachDisplayCounter = readyToChainAttachDisplayCounter + readyToChainAttachDisplayIncrement
readyToChainAttachCounter--
if (readyToChainAttachCounter <= 0) {
readyToChainAttachCounter = 0
isReadyToChainAttach = false
} else {
isReadyToChainAttach = true
}
availableToChainAttachCounter--
if (availableToChainAttachCounter <= 0) {
availableToChainAttachCounter = 0
isAvailableToChainAttach = false
} else {
isAvailableToChainAttach = true
}
}
}
function chainDetachingPhysics() {
if (isDragging !== true) { return }
if (rightDragging === false) { return }
if (UI.projects.foundations.spaces.floatingSpace.settings.detachUsingMouse !== true) { return }
let distanceToChainParent = Math.sqrt(Math.pow(thisObject.payload.position.x - thisObject.payload.targetPosition.x, 2) + Math.pow(thisObject.payload.position.y - thisObject.payload.targetPosition.y, 2))
let ratio = distanceToChainParent / previousDistanceToChainParent
if (previousDistanceToChainParent === 0) {
previousDistanceToChainParent = distanceToChainParent
return
}
previousDistanceToChainParent = distanceToChainParent
if (thisObject.isOnFocus !== true) { return }
if (thisObject.payload.chainParent === undefined) { return }
if (thisObject.payload.parentNode === undefined) { return }
let THRESHOLD = 1.15
if (ratio > THRESHOLD) {
UI.projects.foundations.spaces.designSpace.workspace.executeAction({ node: thisObject.payload.node, name: 'Parent Detach', project: 'Visual-Scripting' })
}
}
function referenceAttachingPhysics() {
referenceAttacchingCounters()
if (thisObject.isOnFocus !== true) { return }
if (isDragging !== true) { return }
if (rightDragging !== true) { return }
if (thisObject.payload.referenceParent !== undefined) { return }
UI.projects.foundations.spaces.floatingSpace.floatingLayer.isProximityPhysicsNeeded = true
let nearbyFloatingObjects = thisObject.payload.floatingObject.nearbyFloatingObjects
let compatibleTypes
let schemaDocument = getSchemaDocument(thisObject.payload.node)
if (schemaDocument !== undefined) {
if (schemaDocument.referencingRules !== undefined) {
compatibleTypes = schemaDocument.referencingRules.compatibleTypes
} else {
return
}
} else {
return
}
let foundCompatible = false
referenceAttachToNode = undefined
isReferenceAttaching = false
for (let i = 0; i < nearbyFloatingObjects.length; i++) {
let nearby = nearbyFloatingObjects[i]
let distance = nearby[0]
let floatingObject = nearby[1]
if (floatingObject.payload === undefined) { continue }
let nearbyNode = floatingObject.payload.node
if (compatibleTypes.indexOf('->' + nearbyNode.type + '->') >= 0 || compatibleTypes === "->*Any Node*->") {
if (schemaDocument.referencingRules.incompatibleTypes !== undefined) {
if (schemaDocument.referencingRules.incompatibleTypes.indexOf('->' + nearbyNode.type + '->') >= 0) {
continue
}
}
if (foundCompatible === false) {
if (distance < thisObject.payload.floatingObject.container.frame.radius * 1.5 + floatingObject.container.frame.radius * 1.5) {
nearbyNode.payload.uiObject.getReadyToReferenceAttach()
isReferenceAttaching = true
referenceAttachToNode = nearbyNode
foundCompatible = true
}
}
nearbyNode.payload.uiObject.showAvailabilityToReferenceAttach()
}
}
function referenceAttacchingCounters() {
if (readyToReferenceAttachDisplayCounter > 15) {
readyToReferenceAttachDisplayIncrement = -0.25
}
if (readyToReferenceAttachDisplayCounter < 5) {
readyToReferenceAttachDisplayIncrement = 0.25
}
readyToReferenceAttachDisplayCounter = readyToReferenceAttachDisplayCounter + readyToReferenceAttachDisplayIncrement
readyToReferenceAttachCounter--
if (readyToReferenceAttachCounter <= 0) {
readyToReferenceAttachCounter = 0
isReadyToReferenceAttach = false
} else {
isReadyToReferenceAttach = true
}
availableToReferenceAttachCounter--
if (availableToReferenceAttachCounter <= 0) {
availableToReferenceAttachCounter = 0
isAvailableToReferenceAttach = false
} else {
isAvailableToReferenceAttach = true
}
}
}
function referenceDetachingPhysics() {
if (isDragging !== true) { return }
if (thisObject.payload === undefined) { return }
if (thisObject.payload.floatingObject.isFrozen === true) { return }
if (rightDragging === false) { return }
if (UI.projects.foundations.spaces.floatingSpace.settings.detachUsingMouse !== true) { return }
if (thisObject.payload.referenceParent === undefined) { return }
let distanceToReferenceParent = Math.sqrt(Math.pow(thisObject.payload.position.x - thisObject.payload.referenceParent.payload.position.x, 2) + Math.pow(thisObject.payload.position.y - thisObject.payload.referenceParent.payload.position.y, 2))
let ratio = distanceToReferenceParent / previousDistanceToReferenceParent
if (previousDistanceToReferenceParent === 0) {
previousDistanceToReferenceParent = distanceToReferenceParent
return
}
previousDistanceToReferenceParent = distanceToReferenceParent
if (thisObject.isOnFocus !== true) { return }
let THRESHOLD = 1.15
if (ratio > THRESHOLD) {
UI.projects.foundations.spaces.designSpace.workspace.executeAction({ node: thisObject.payload.node, name: 'Reference Detach', project: 'Visual-Scripting' })
}
}
function highlightPhisycs() {
highlightCounter--
if (highlightCounter < 0) {
highlightCounter = 0
isHighlighted = false
}
}
function runningAtBackendPhisycs() {
runningAtBackendCounter--
if (runningAtBackendCounter < 0) {
runningAtBackendCounter = 0
isRunningAtBackend = false
}
}
function errorMessagePhisycs() {
errorMessageCounter--
if (errorMessageCounter < 0) {
errorMessageCounter = 0
thisObject.hasError = false
if (thisObject.uiObjectMessage.type === 'Error') {
thisObject.uiObjectMessage.text = undefined
thisObject.uiObjectMessage.type = undefined
}
}
}
function warningMessagePhisycs() {
warningMessageCounter--
if (warningMessageCounter < 0) {
warningMessageCounter = 0
thisObject.hasWarning = false
if (thisObject.uiObjectMessage.type === 'Warning') {
thisObject.uiObjectMessage.text = undefined
thisObject.uiObjectMessage.type = undefined
}
}
}
function infoMessagePhisycs() {
infoMessageCounter--
if (infoMessageCounter < 0) {
infoMessageCounter = 0
thisObject.hasInfo = false
if (thisObject.uiObjectMessage.type === 'Info') {
thisObject.uiObjectMessage.text = undefined
thisObject.uiObjectMessage.type = undefined
}
}
}
function valuePhisycs() {
valueCounter--
if (valueCounter < 0) {
valueCounter = 0
hasValue = false
}
}
function percentagePhisycs() {
percentageCounter--
if (percentageCounter < 0) {
percentageCounter = 0
hasPercentage = false
}
}
function statusPhisycs() {
statusCounter--
if (statusCounter < 0) {
statusCounter = 0
hasStatus = false
}
}
}
function heartBeatPhysics() {
if (lastHeartBeat !== undefined) {
const ONE_MIN = 60000
nowTimestamp = (new Date()).valueOf()
if (nowTimestamp - lastHeartBeat.valueOf() > ONE_MIN) {
lastHeartBeat = undefined
thisObject.isRunning = false
valueCounter = 0
}
} else {
thisObject.isRunning = false
}
}
function childrenRunningPhysics() {
let schemaDocument = getSchemaDocument(thisObject.payload.node)
if (schemaDocument.childrenNodesProperties === undefined) { return }
let monitorChildrenRunning = false
for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) {
let property = schemaDocument.childrenNodesProperties[i]
if (property.monitorChildrenRunning === true) {
let children = thisObject.payload.node[property.name]
if (children === undefined) { continue }
let totalRunning = 0
for (let j = 0; j < children.length; j++) {
let child = children[j]
if (child.payload !== undefined) {
if (child.payload.uiObject.isRunning === true) {
totalRunning++
}
}
}
if (totalRunning > 0) {
setStatus(totalRunning + ' / ' + children.length + ' Running')
thisObject.isRunning = true
} else {
thisObject.isRunning = false
valueCounter = 0
}
monitorChildrenRunning = true
return
}
}
if (monitorChildrenRunning === false) {
heartBeatPhysics()
}
}
function getReadyToChainAttach() {
readyToChainAttachCounter = 10
}
function showAvailabilityToChainAttach() {
availableToChainAttachCounter = 10
}
function getReadyToReferenceAttach() {
readyToReferenceAttachCounter = 10
}
function showAvailabilityToReferenceAttach() {
availableToReferenceAttachCounter = 10
}
function highlight(counter) {
isHighlighted = true
if (counter !== undefined) {
highlightCounter = counter
} else {
highlightCounter = 30
}
}
function runningAtBackend() {
isRunningAtBackend = true
runningAtBackendCounter = 5
}
function setErrorMessage(message, duration, docs) {
if (message !== undefined) {
errorMessage = message
errorDocs = docs
thisObject.hasError = true
if (duration === undefined) { duration = 2 }
errorMessageCounter = 100 * duration
/*
Next, we are going to try to inform the parent that this
node has an error, as a way to show the end user where the
node with error is. This is useful to detect errors in nodes
that are located at braches that are collapsed.
*/
if (thisObject.payload !== undefined) {
if (thisObject.payload.parentNode !== undefined) {
if (thisObject.payload.parentNode.payload !== undefined) {
if (thisObject.payload.parentNode.payload.floatingObject !== undefined) {
if (thisObject.payload.floatingObject.isCollapsed === true || thisObject.payload.floatingObject.isParentCollapsed === true) {
if (thisObject.payload.parentNode.payload.uiObject.hasError !== true) {
thisObject.payload.parentNode.payload.uiObject.setErrorMessage('Error Inside this Branch')
}
}
}
}
}
}
}
}
function resetErrorMessage() {
errorMessage = undefined
errorDocs = undefined
thisObject.hasError = false
if (thisObject.uiObjectMessage.type === 'Error') {
thisObject.uiObjectMessage.text = undefined
thisObject.uiObjectMessage.type = undefined
}
}
function setWarningMessage(message, duration, docs) {
if (message !== undefined) {
warningMessage = message
warningDocs = docs
thisObject.hasWarning = true
if (duration === undefined) { duration = 1 }
warningMessageCounter = 100 * duration
/*
Next, we are going to try to inform the parent that this
node has an warning, as a way to show the end user where the
node with warning is. This is useful to detect warnings in nodes
that are located at braches that are collapsed.
*/
if (thisObject.payload !== undefined) {
if (thisObject.payload.parentNode !== undefined) {
if (thisObject.payload.parentNode.payload !== undefined) {
if (thisObject.payload.parentNode.payload.floatingObject !== undefined) {
if (thisObject.payload.parentNode.payload.floatingObject.isCollapsed === true || thisObject.payload.parentNode.payload.floatingObject.isParentCollapsed === true) {
if (thisObject.payload.parentNode.payload.uiObject !== true) {
thisObject.payload.parentNode.payload.uiObject.setWarningMessage('Warning Inside this Branch')
}
}
}
}
}
}
}
}
function resetWarningMessage() {
warningMessage = undefined
warningDocs = undefined
thisObject.hasWarning = false
if (thisObject.uiObjectMessage.type === 'Warning') {
thisObject.uiObjectMessage.text = undefined
thisObject.uiObjectMessage.type = undefined
}
}
function setInfoMessage(message, duration, docs) {
if (message !== undefined) {
infoMessage = message
infoDocs = docs
thisObject.hasInfo = true
if (duration === undefined) { duration = 1 }
infoMessageCounter = 100 * duration
/*
Next, we are going to try to inform the parent that this
node has an info, as a way to show the end user where the
node with info is. This is useful to detect infos in nodes
that are located at braches that are collapsed.
*/
if (thisObject.payload !== undefined) {
if (thisObject.payload.parentNode !== undefined) {
if (thisObject.payload.parentNode.payload !== undefined) {
if (thisObject.payload.parentNode.payload.floatingObject !== undefined) {
if (thisObject.payload.parentNode.payload.floatingObject.isCollapsed === true || thisObject.payload.parentNode.payload.floatingObject.isParentCollapsed === true) {
if (thisObject.payload.parentNode.payload.uiObject !== true) {
thisObject.payload.parentNode.payload.uiObject.setInfoMessage('Info Inside this Branch')
}
}
}
}
}
}
}
}
function resetInfoMessage() {
infoMessage = undefined
infoDocs = undefined
thisObject.hasInfo = false
if (thisObject.uiObjectMessage.type === 'Info') {
thisObject.uiObjectMessage.text = undefined
thisObject.uiObjectMessage.type = undefined
}
}
function getValue() {
return currentValue
}
function setValue(value, counter, minDecimals) {
if (value !== undefined) {
currentValue = value
hasValue = true
valueMinDecimals = minDecimals
if (counter !== undefined) {
valueCounter = counter
} else {
valueCounter = 100
}
}
}
function resetValue() {
currentValue = undefined
hasValue = false
valueCounter = 0
}
function setPercentage(percentage, counter) {
if (percentage !== undefined) {
currentPercentage = percentage
hasPercentage = true
if (counter !== undefined) {
percentageCounter = counter
} else {
percentageCounter = 100
}
}
}
function resetPercentage() {
currentPercentage = undefined
hasPercentage = false
percentageCounter = 0
}
function setStatus(status, counter) {
if (status !== undefined) {
currentStatus = status
hasStatus = true
if (counter !== undefined) {
statusCounter = counter
} else {
statusCounter = 100
}
}
}
function resetStatus() {
currentStatus = undefined
hasStatus = false
statusCounter = 0
}
function heartBeat() {
lastHeartBeat = new Date()
thisObject.isRunning = true
if (onRunningCallBackFunctionWasCalled === false) {
onRunningCallBackFunctionWasCalled = true
if (onRunningCallBackFunction !== undefined) {
onRunningCallBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
}
}
}
function reset() {
resetErrorMessage()
resetWarningMessage()
resetInfoMessage()
resetPercentage()
resetValue()
resetStatus()
}
function run(pEventsServerClient, callBackFunction) {
finalizeEventsServerClient()
reset()
eventsServerClient = pEventsServerClient
/* We setup the circular progress bar. */
if (thisObject.circularProgressBar !== undefined) {
thisObject.circularProgressBar.finalize()
}
thisObject.circularProgressBar = newCircularProgressBar()
thisObject.circularProgressBar.initialize(thisObject.payload, eventsServerClient)
thisObject.circularProgressBar.fitFunction = thisObject.fitFunction
thisObject.circularProgressBar.container = thisObject.container
setupRunningEventListener(callBackFunction)
setupErrorEventListener(callBackFunction)
setupWarningEventListener()
setupInfoEventListener()
function setupRunningEventListener(callBackFunction) {
/* We will wait to hear the Running event in order to confirm the execution was really started */
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
eventsServerClient.listenToEvent(key, 'Running', undefined, 'UiObject', onResponse, onRunning)
onRunningCallBackFunction = callBackFunction
function onResponse(message) {
eventSubscriptionIdOnRunning = message.eventSubscriptionId
}
function onRunning() {
if (thisObject.payload === undefined) { return }
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
eventsServerClient.stopListening(key, eventSubscriptionIdOnRunning, 'UiObject')
thisObject.isRunning = true
if (callBackFunction !== undefined) {
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
onRunningCallBackFunctionWasCalled = true
}
}
/*
While it is running, it can happen that it naturally stops or is stopped not from the UI but from other means.
In those cases, the stop function would never be called (from the UI). So what we will do is to call it from
here with and event, and passing our own callBackFunction. In case there is an external source stopping this,
this will produce an execution of the callback with our event, which will produce that the menu item is restored
to its default value.
If on the other side, it is executed from the UI, then we will be processing the Stopped event twice, which in
both cases will reset the menu item to its default state.
*/
let event = {
type: 'Secondary Action Already Executed'
}
stop(callBackFunction, event)
}
function setupErrorEventListener(callBackFunction) {
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
eventsServerClient.listenToEvent(key, 'Error', undefined, key, onResponse, onError)
function onResponse(message) {
eventSubscriptionIdOnError = message.eventSubscriptionId
}
async function onError(message) {
let uiObject = await getTargetUiObject(message)
uiObject.setErrorMessage(message.event.errorMessage, 10, message.event.docs)
let event = {
type: 'Secondary Action Already Executed'
}
completeStop(callBackFunction, event)
}
}
function setupWarningEventListener() {
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
eventsServerClient.listenToEvent(key, 'Warning', undefined, key, onResponse, onWarning)
function onResponse(message) {
eventSubscriptionIdOnWarning = message.eventSubscriptionId
}
async function onWarning(message) {
let uiObject = await getTargetUiObject(message)
uiObject.setWarningMessage(message.event.warningMessage, 10, message.event.docs)
}
}
function setupInfoEventListener() {
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
eventsServerClient.listenToEvent(key, 'Info', undefined, key, onResponse, onInfo)
function onResponse(message) {
eventSubscriptionIdOnInfo = message.eventSubscriptionId
}
async function onInfo(message) {
let uiObject = await getTargetUiObject(message)
uiObject.setInfoMessage(message.event.infoMessage, 10, message.event.docs)
}
}
}
async function getTargetUiObject(message) {
let uiObject = thisObject
if (message.event.nodeId !== undefined) {
let targetNode = await UI.projects.foundations.spaces.designSpace.workspace.getNodeById(message.event.nodeId)
if (targetNode !== undefined) {
if (targetNode.payload !== undefined) {
if (targetNode.payload.uiObject !== undefined) {
uiObject = targetNode.payload.uiObject
}
}
}
}
return uiObject
}
function stop(callBackFunction, event, requestFromUI) {
let wasStopped = false
/* We will wait for the event that the execution was terminated in order to call back the menu item */
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
eventsServerClient.listenToEvent(key, 'Stopped', undefined, 'UiObject', onResponse, onStopped)
function onResponse(message) {
eventSubscriptionIdOnStopped = message.eventSubscriptionId
}
function onStopped() {
completeStop(callBackFunction, event)
wasStopped = true
}
/*
When the request comes from the UI, we need to consider the possibility that the client is down or it
was restarted while this node was running.
*/
if (requestFromUI === true) {
/*
It can happen that the client is down, the task is down, session is down of for whatever reason there is no
answer to the command to stop. In those cases, we will stop execute the onStopped function anyways so as to
return the UI to its default state.
*/
setTimeout(returnToDefaultState, 15000)
function returnToDefaultState() {
if (wasStopped === false) {
completeStop(callBackFunction, event)
}
}
}
}
function completeStop(callBackFunction, event) {
if (thisObject.payload === undefined) { return }
if (callBackFunction !== undefined) {
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, event)
}
if (thisObject.circularProgressBar !== undefined) {
thisObject.circularProgressBar.finalize()
thisObject.circularProgressBar = undefined
}
thisObject.isRunning = false
hasValue = false
hasPercentage = false
hasStatus = false
lastHeartBeat = undefined
finalizeEventsServerClient()
}
function iconPhysics() {
icon = UI.projects.foundations.spaces.designSpace.getIconByProjectAndType(thisObject.payload.node.project, thisObject.payload.node.type)
let schemaDocument = getSchemaDocument(thisObject.payload.node)
/*
If we want this object to have an alternative icon (defined on a list of possible icons) but
this definition does not belong to the current node but to a relative of it, then
the property to use is alternativeIcons with a value of a string defining the nodePath to the
node that actually has the icon list.
On the other hand, if this icon has the icon list definition, then the value of alternativeIcons
shoudl be an array of the possible icons. Then to pick one icon from that list we will check
the config.condeName of the node to see with which icon on the list matches.
Finally, if the node we are pointing to does not have a config or does not have a list of
alternativeIcons, we will just use that node's icon for the current node.
*/
if (schemaDocument.alternativeIcons !== undefined) {
let nodeToUse = thisObject.payload.node
if (schemaDocument.alternativeIcons === 'Use Parent') {
if (thisObject.payload.node.payload.parentNode !== undefined) {
nodeToUse = thisObject.payload.node.payload.parentNode
}
}
if (schemaDocument.alternativeIcons === 'Use Reference Parent') {
if (thisObject.payload.node.payload.referenceParent !== undefined) {
nodeToUse = thisObject.payload.node.payload.referenceParent
}
}
if (schemaDocument.alternativeIcons === 'Use Reference Grandparent') {
if (thisObject.payload.node.payload.referenceParent !== undefined) {
if (thisObject.payload.node.payload.referenceParent.payload !== undefined) {
if (thisObject.payload.node.payload.referenceParent.payload.referenceParent !== undefined) {
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.referenceParent
}
}
}
}
if (schemaDocument.alternativeIcons === 'Use Reference Parent Parent') {
if (thisObject.payload.node.payload.referenceParent !== undefined) {
if (thisObject.payload.node.payload.referenceParent.payload !== undefined) {
if (thisObject.payload.node.payload.referenceParent.payload.parentNode !== undefined) {
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode
}
}
}
}
schemaDocument = getSchemaDocument(nodeToUse)
let config = nodeToUse.config
if (config !== undefined && (Array.isArray(schemaDocument.alternativeIcons) === true)) {
try {
config = JSON.parse(config)
let alternativeIcon
let iconName
for (let i = 0; i < schemaDocument.alternativeIcons.length; i++) {
alternativeIcon = schemaDocument.alternativeIcons[i]
if (alternativeIcon.codeName === config.codeName) {
iconName = alternativeIcon.iconName
}
}
let newIcon = UI.projects.foundations.spaces.designSpace.getIconByProjectAndName(nodeToUse.project, iconName)
if (newIcon !== undefined) {
icon = newIcon
}
} catch (err) {
nodeToUse.payload.uiObject.setErrorMessage('The config is not well formatted as a JSON object.')
}
} else {
if (schemaDocument.icon !== undefined) {
let newIcon = UI.projects.foundations.spaces.designSpace.getIconByProjectAndName(nodeToUse.project, schemaDocument.icon)
if (newIcon !== undefined) {
icon = newIcon
}
}
}
}
executingIcon = UI.projects.foundations.spaces.designSpace.getIconByProjectAndName('Foundations', 'bitcoin')
}
function onFocus() {
thisObject.isOnFocus = true
if (thisObject.payload !== undefined && thisObject.isOnFocus === true && thisObject.payload.referenceParent !== undefined) {
if (thisObject.payload.referenceParent.payload !== undefined) {
if (thisObject.payload.referenceParent.payload.uiObject !== undefined) {
thisObject.payload.referenceParent.payload.uiObject.isShowing = true
}
}
}
}
function onNotFocus() {
thisObject.isOnFocus = false
if (thisObject.codeEditor !== undefined) {
thisObject.codeEditor.deactivate()
}
if (thisObject.configEditor !== undefined) {
thisObject.configEditor.deactivate()
}
if (thisObject.conditionEditor !== undefined) {
thisObject.conditionEditor.deactivate()
}
if (thisObject.formulaEditor !== undefined) {
thisObject.formulaEditor.deactivate()
}
if (thisObject.payload !== undefined &&
thisObject.isOnFocus === false &&
thisObject.payload.referenceParent !== undefined &&
thisObject.payload.referenceParent.payload !== undefined &&
thisObject.payload.referenceParent.payload.uiObject !== undefined) {
thisObject.payload.referenceParent.payload.uiObject.isShowing = false
}
}
function onDisplace(event) {
thisObject.uiObjectTitle.exitEditMode()
}
function onDragStarted(event) {
thisObject.uiObjectTitle.exitEditMode()
if (thisObject.codeEditor !== undefined) {
thisObject.codeEditor.deactivate()
}
if (thisObject.configEditor !== undefined) {
thisObject.configEditor.deactivate()
}
if (thisObject.conditionEditor !== undefined) {
thisObject.conditionEditor.deactivate()
}
if (thisObject.formulaEditor !== undefined) {
thisObject.formulaEditor.deactivate()
}
isDragging = true
if (event.button === 2) {
rightDragging = true
} else {
rightDragging = false
}
previousDistanceToReferenceParent = undefined
previousDistanceToChainParent = undefined
}
function onDragFinished(event) {
if (isChainAttaching === true) {
UI.projects.foundations.spaces.designSpace.workspace.executeAction({ node: thisObject.payload.node, name: 'Parent Attach', project: 'Visual-Scripting', relatedNode: chainAttachToNode })
chainAttachToNode = undefined
isChainAttaching = false
/* We want to avoid the situation in which we are attaching a node to its parent and at the same time referencing another node. */
isReferenceAttaching = false
}
if (isReferenceAttaching === true) {
UI.projects.foundations.spaces.designSpace.workspace.executeAction({ node: thisObject.payload.node, name: 'Reference Attach', project: 'Visual-Scripting', relatedNode: referenceAttachToNode })
referenceAttachToNode = undefined
isReferenceAttaching = false
}
isDragging = false
}
function drawBackground() {
if (thisObject.isOnFocus === false) {
drawReferenceLine()
drawChainLine()
if (isDragging === false && thisObject.isOnFocus === true) {
thisObject.menu.drawBackground()
}
}
if (thisObject.circularProgressBar !== undefined) {
thisObject.circularProgressBar.drawBackground()
}
}
function drawMiddleground() {
if (thisObject.isOnFocus === false) {
drawErrorMessage()
drawWarningMessage()
drawInfoMessage()
drawValue()
drawPercentage()
drawStatus()
thisObject.uiObjectTitle.draw()
thisObject.uiObjectMessage.draw()
drawNodeType()
}
}
function drawForeground() {
if (thisObject.isOnFocus === false) {
drawBodyAndPicture()
}
if (thisObject.circularProgressBar !== undefined) {
thisObject.circularProgressBar.drawForeground()
}
}
function drawOnFocus() {
if (thisObject.isOnFocus === true) {
drawReferenceLine()
drawChainLine()
if (thisObject.codeEditor !== undefined) {
thisObject.codeEditor.drawBackground()
thisObject.codeEditor.drawForeground()
}
if (thisObject.configEditor !== undefined) {
thisObject.configEditor.drawBackground()
thisObject.configEditor.drawForeground()
}
if (thisObject.conditionEditor !== undefined) {
thisObject.conditionEditor.drawBackground()
thisObject.conditionEditor.drawForeground()
}
if (thisObject.formulaEditor !== undefined) {
thisObject.formulaEditor.drawBackground()
thisObject.formulaEditor.drawForeground()
}
let drawMenu = true
let drawTitle = true
if (thisObject.codeEditor !== undefined) {
if (thisObject.codeEditor.visible === true) {
drawMenu = false
drawTitle = false
}
}
if (thisObject.configEditor !== undefined) {
if (thisObject.configEditor.visible === true) {
drawMenu = false
drawTitle = false
}
}
if (thisObject.conditionEditor !== undefined) {
if (thisObject.conditionEditor.visible === true) {
drawMenu = false
drawTitle = false
}
}
if (thisObject.formulaEditor !== undefined) {
if (thisObject.formulaEditor.visible === true) {
drawMenu = false
drawTitle = false
}
}
if (drawMenu === true) {
drawBodyAndPicture()
if (isDragging === false) {
thisObject.menu.drawBackground()
thisObject.menu.drawForeground()
}
}
drawErrorMessage()
drawWarningMessage()
drawInfoMessage()
drawValue()
drawPercentage()
drawStatus()
if (drawTitle === true) {
thisObject.uiObjectTitle.draw()
thisObject.uiObjectMessage.draw()
}
drawNodeType()
}
}
function drawChainLine() {
if (UI.projects.foundations.spaces.floatingSpace.drawChainLines === false) { return }
if (thisObject.payload.chainParent === undefined) { return }
if (thisObject.payload.chainParent.payload === undefined) { return }
let targetPoint = {
x: thisObject.payload.chainParent.payload.floatingObject.container.frame.position.x,
y: thisObject.payload.chainParent.payload.floatingObject.container.frame.position.y
}
let position = {
x: 0,
y: 0
}
targetPoint = UI.projects.foundations.spaces.floatingSpace.container.frame.frameThisPoint(targetPoint)
position = thisObject.container.frame.frameThisPoint(position)
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
targetPoint = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(targetPoint)
position = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(position)
}
if (thisObject.payload.floatingObject.container.frame.radius > 1) {
let LINE_STYLE = UI_COLOR.TITANIUM_YELLOW
if (thisObject.payload.floatingObject.angleToParent !== ANGLE_TO_PARENT.NOT_FIXED) {
LINE_STYLE = UI_COLOR.GOLDEN_ORANGE
}
if (thisObject.payload.floatingObject.isFrozen === true) {
LINE_STYLE = UI_COLOR.TURQUOISE
}
if (newUiObjectCounter > 0) {
LINE_STYLE = UI_COLOR.GREY
}
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(position.x, position.y)
browserCanvasContext.lineTo(targetPoint.x, targetPoint.y)
browserCanvasContext.strokeStyle = 'rgba(' + LINE_STYLE + ', 1)'
browserCanvasContext.setLineDash([0, chainLineCounter, 2, 3, 0, 500 - chainLineCounter])
browserCanvasContext.lineWidth = 2
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(position.x, position.y)
browserCanvasContext.lineTo(targetPoint.x, targetPoint.y)
browserCanvasContext.strokeStyle = 'rgba(' + LINE_STYLE + ', 1)'
browserCanvasContext.setLineDash([3, 47])
browserCanvasContext.lineWidth = 3
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(position.x, position.y)
browserCanvasContext.lineTo(targetPoint.x, targetPoint.y)
browserCanvasContext.strokeStyle = 'rgba(' + LINE_STYLE + ', 1)'
browserCanvasContext.setLineDash([1, 9])
browserCanvasContext.lineWidth = 1
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
if (thisObject.payload.floatingObject.container.frame.radius > 0.5) {
let radius = 1
browserCanvasContext.beginPath()
browserCanvasContext.arc(targetPoint.x, targetPoint.y, radius, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
browserCanvasContext.fill()
}
}
function drawReferenceLine() {
if (UI.projects.foundations.spaces.floatingSpace.drawReferenceLines === false && thisObject.isOnFocus === false) { return }
if (thisObject.payload.referenceParent === undefined) { return }
if (thisObject.payload.referenceParent.payload === undefined) { return }
if (thisObject.payload.referenceParent.payload.floatingObject === undefined) { return }
if (thisObject.payload.referenceParent.payload.floatingObject.isParentCollapsed === true && thisObject.isOnFocus === false) { return }
let targetPoint = {
x: thisObject.payload.referenceParent.payload.position.x,
y: thisObject.payload.referenceParent.payload.position.y
}
let position = {
x: 0,
y: 0
}
targetPoint = UI.projects.foundations.spaces.floatingSpace.container.frame.frameThisPoint(targetPoint)
position = thisObject.container.frame.frameThisPoint(position)
if (thisObject.isOnFocus === true) {
targetPoint = thisObject.fitFunction(targetPoint)
}
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
position = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(position)
targetPoint = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(targetPoint)
}
let LINE_STYLE = UI_COLOR.GREY
if (thisObject.payload.floatingObject.container.frame.radius > 1) {
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(position.x, position.y)
browserCanvasContext.lineTo(targetPoint.x, targetPoint.y)
browserCanvasContext.strokeStyle = 'rgba(' + LINE_STYLE + ', 1)'
browserCanvasContext.setLineDash([1, 9])
browserCanvasContext.lineWidth = 0.75
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
browserCanvasContext.beginPath()
browserCanvasContext.moveTo(position.x, position.y)
browserCanvasContext.lineTo(targetPoint.x, targetPoint.y)
browserCanvasContext.strokeStyle = 'rgba(' + LINE_STYLE + ', 1)'
browserCanvasContext.setLineDash([0, referenceLineCounter, 1, 9, 2, 8, 3, 7, 4, 6, 0, 500 - referenceLineCounter])
browserCanvasContext.lineWidth = 4
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
if (thisObject.payload.floatingObject.container.frame.radius > 0.5) {
let radius = 1
browserCanvasContext.beginPath()
browserCanvasContext.arc(targetPoint.x, targetPoint.y, radius, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
browserCanvasContext.fill()
}
}
function isEditorVisible() {
if (thisObject.codeEditor !== undefined) {
if (thisObject.codeEditor.visible === true) { return true }
}
if (thisObject.configEditor !== undefined) {
if (thisObject.configEditor.visible === true) { return true }
}
if (thisObject.conditionEditor !== undefined) {
if (thisObject.conditionEditor.visible === true) { return true }
}
if (thisObject.formulaEditor !== undefined) {
if (thisObject.formulaEditor.visible === true) { return true }
}
}
function drawNodeType() {
if (isEditorVisible() === true) { return }
/* Text Follows */
let position = {
x: 0,
y: 0
}
position = thisObject.container.frame.frameThisPoint(position)
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
position = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(position)
let schemaDocument = getSchemaDocument(thisObject.payload.node)
if (schemaDocument.inMapMode !== undefined) {
if (schemaDocument.inMapMode.showNodeType === false) {
return
}
}
}
let radius = thisObject.payload.floatingObject.container.frame.radius
/* Label Text */
let labelPoint
let fontSize = thisObject.payload.floatingObject.currentFontSize
let lineSeparator = thisObject.payload.floatingObject.currentFontSize * 1.2
let label
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
if (radius > 6) {
const MAX_LABEL_LENGTH = 30
label = thisObject.payload.node.type
label = addIndexNumber(label)
if (label !== undefined) {
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
let schemaDocument = getSchemaDocument(thisObject.payload.node)
if (schemaDocument !== undefined) {
if (schemaDocument.isHierarchyHead !== true && schemaDocument.isProjectHead !== true) {
return
}
}
if (label.length > MAX_LABEL_LENGTH) {
label = label.substring(0, MAX_LABEL_LENGTH) + '...'
}
}
if (thisObject.isOnFocus === true) {
if (label.length > MAX_LABEL_LENGTH) {
label = label.substring(0, MAX_LABEL_LENGTH) + '...'
}
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y + radius * 2 / 3 + lineSeparator * 1 + 30
}
} else {
/* Split the line into Phrases */
let phrases = splitTextIntoPhrases(label, 2)
for (let i = 0; i < phrases.length; i++) {
let phrase = phrases[i]
labelPoint = {
x: position.x - getTextWidth(phrase) / 2,
y: position.y + thisObject.payload.floatingObject.currentImageSize / 2 + lineSeparator * (1 + i)
}
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === false) {
printMessage(phrase)
}
}
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === false) {
return
}
}
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
labelPoint.x = position.x - getTextWidth(label) / 2,
labelPoint.y = position.y + 50 / 2 + lineSeparator * 2
}
printMessage(label)
function printMessage(text) {
browserCanvasContext.fillStyle = thisObject.payload.floatingObject.nameStrokeStyle
browserCanvasContext.fillText(text, labelPoint.x, labelPoint.y)
}
}
}
}
function drawErrorMessage() {
if (thisObject.hasError === false) { return }
thisObject.uiObjectMessage.text = errorMessage
thisObject.uiObjectMessage.type = 'Error'
thisObject.uiObjectMessage.docs = errorDocs
}
function drawWarningMessage() {
if (thisObject.hasError === true) { return }
if (thisObject.hasWarning !== true) { return }
thisObject.uiObjectMessage.text = warningMessage
thisObject.uiObjectMessage.type = 'Warning'
thisObject.uiObjectMessage.docs = warningDocs
}
function drawInfoMessage() {
if (thisObject.hasError === true) { return }
if (thisObject.hasWarning === true) { return }
if (thisObject.hasInfo !== true) { return }
thisObject.uiObjectMessage.text = infoMessage
thisObject.uiObjectMessage.type = 'Info'
thisObject.uiObjectMessage.docs = infoDocs
}
function drawValue() {
if (currentValue === null) { return }
if (hasValue === false) { return }
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) { return }
if (thisObject.payload === undefined) { return }
if ((thisObject.payload.floatingObject.isCollapsed === true && thisObject.payload.floatingObject.collapsedManually === false) || thisObject.payload.floatingObject.isParentCollapsed === true) { return }
// if (currentValue === undefined || currentValue === '') { return }
/* Text Follows */
let position = {
x: 0,
y: 0
}
position = thisObject.container.frame.frameThisPoint(position)
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
position = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(position)
}
let radius = thisObject.payload.floatingObject.container.frame.radius
/* Label Text */
let labelPoint
let fontSize = thisObject.payload.floatingObject.currentFontSize
let lineSeparator = thisObject.payload.floatingObject.currentFontSize * 1.2
let label
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
if (radius > 6) {
const MAX_LABEL_LENGTH = 70
label = currentValue
if (!isNaN(currentValue)) {
if (currentValue.toFixed !== undefined) {
label = dynamicDecimals(currentValue, valueMinDecimals)
}
}
if (label !== undefined) {
if (label.length > MAX_LABEL_LENGTH) {
label = label.substring(0, MAX_LABEL_LENGTH) + '...'
}
if (label.length > 30) {
fontSize = fontSize * 2 / 3
}
if (thisObject.valueAtAngle === true && thisObject.payload.angle !== undefined) {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y
}
labelPoint.x = labelPoint.x + radius * 7 / 3 * Math.cos(toRadians(thisObject.payload.angle + thisObject.valueAngleOffset))
labelPoint.y = labelPoint.y + radius * 7 / 3 * Math.sin(toRadians(thisObject.payload.angle + thisObject.valueAngleOffset))
} else {
if (thisObject.isOnFocus === true) {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y + radius * 2 / 3 + lineSeparator * 5 + 30
}
} else {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y + thisObject.payload.floatingObject.currentImageSize / 2 + lineSeparator * 5
}
}
}
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TURQUOISE + ', 1)'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
}
}
function drawPercentage() {
if (hasPercentage === false) { return }
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) { return }
if (thisObject.payload === undefined) { return }
if ((thisObject.payload.floatingObject.isCollapsed === true && thisObject.payload.floatingObject.collapsedManually === false) || thisObject.payload.floatingObject.isParentCollapsed === true) { return }
let position = {
x: 0,
y: 0
}
position = thisObject.container.frame.frameThisPoint(position)
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
position = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(position)
}
let radius = thisObject.payload.floatingObject.container.frame.radius
/* Label Text */
let labelPoint
let fontSize = thisObject.payload.floatingObject.currentFontSize
let lineSeparator = thisObject.payload.floatingObject.currentFontSize * 1.2
let label
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
if (radius > 6) {
const MAX_LABEL_LENGTH = 65
label = Number(currentPercentage) + '%'
if (label.length > MAX_LABEL_LENGTH) {
label = label.substring(0, MAX_LABEL_LENGTH) + '...'
}
if (thisObject.percentageAtAngle === true && thisObject.payload.angle !== undefined) {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y
}
labelPoint.x = labelPoint.x + radius * 7 / 3 * Math.cos(toRadians(thisObject.payload.angle + thisObject.percentageAngleOffset))
labelPoint.y = labelPoint.y + radius * 7 / 3 * Math.sin(toRadians(thisObject.payload.angle + thisObject.percentageAngleOffset)) + lineSeparator * 1
} else {
if (thisObject.isOnFocus === true) {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y + radius * 2 / 3 + lineSeparator * 6 + 30
}
} else {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y + thisObject.payload.floatingObject.currentImageSize / 2 + lineSeparator * 6
}
}
}
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TURQUOISE + ', 1)'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
}
function drawStatus() {
if (hasStatus === false) { return }
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) { return }
let position = {
x: 0,
y: 0
}
position = thisObject.container.frame.frameThisPoint(position)
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
position = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(position)
}
let radius = thisObject.payload.floatingObject.container.frame.radius
/* Label Text */
let labelPoint
let fontSize = thisObject.payload.floatingObject.currentFontSize * 6 / 4 / 2
let lineSeparator = thisObject.payload.floatingObject.currentFontSize * 1.2
let label
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
if (radius > 6) {
const MAX_LABEL_LENGTH = 120
label = currentStatus
if (label !== undefined) {
if (label.length > MAX_LABEL_LENGTH) {
label = label.substring(0, MAX_LABEL_LENGTH) + '...'
}
if (thisObject.statusAtAngle === true && thisObject.payload.angle !== undefined) {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y
}
labelPoint.x = labelPoint.x + radius * 7 / 3 * Math.cos(toRadians(thisObject.payload.angle + thisObject.statusAngleOffset))
labelPoint.y = labelPoint.y + radius * 7 / 3 * Math.sin(toRadians(thisObject.payload.angle + thisObject.statusAngleOffset)) + lineSeparator * 2
} else {
if (thisObject.isOnFocus === true) {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y + radius * 2 / 3 + lineSeparator * 4 + 30
}
} else {
labelPoint = {
x: position.x - getTextWidth(label) / 2,
y: position.y + thisObject.payload.floatingObject.currentImageSize / 2 + lineSeparator * 4
}
}
}
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 1)'
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
}
}
}
function addIndexNumber(label) {
switch (thisObject.payload.node.type) {
case 'Phase': {
let parent = thisObject.payload.parentNode
if (parent !== undefined) {
let granParent = parent.payload.parentNode
if (granParent !== undefined) {
if (granParent.type === 'Initial Definition') {
return label + ' #' + 0
}
}
for (let i = 0; i < parent.phases.length; i++) {
let phase = parent.phases[i]
if (phase.id === thisObject.payload.node.id) {
label = label + ' #' + (i + 1)
return label
}
}
} else {
return label
}
break
}
case 'Situation': {
let parent = thisObject.payload.parentNode
if (parent !== undefined) {
for (let i = 0; i < parent.situations.length; i++) {
let situation = parent.situations[i]
if (situation.id === thisObject.payload.node.id) {
label = label + ' #' + (i + 1)
return label
}
}
} else {
return label
}
break
}
case 'Condition': {
let parent = thisObject.payload.parentNode
if (parent !== undefined) {
for (let i = 0; i < parent.conditions.length; i++) {
let condition = parent.conditions[i]
if (condition.id === thisObject.payload.node.id) {
label = label + ' #' + (i + 1)
return label
}
}
} else {
return label
}
break
}
default: {
return label
}
}
}
function drawBodyAndPicture() {
let position = {
x: thisObject.container.frame.position.x,
y: thisObject.container.frame.position.y
}
position = thisObject.container.frame.frameThisPoint(position)
if (thisObject.isShowing === true) {
position = thisObject.fitFunction(position)
}
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
position = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(position)
}
let radius = thisObject.payload.floatingObject.container.frame.radius
if (radius > 0.5) {
let VISIBLE_RADIUS = 5
let visiblePosition = {
x: thisObject.container.frame.position.x,
y: thisObject.container.frame.position.y
}
visiblePosition = thisObject.container.frame.frameThisPoint(visiblePosition)
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
visiblePosition = UI.projects.foundations.spaces.floatingSpace.transformPointToMap(visiblePosition)
radius = UI.projects.foundations.spaces.floatingSpace.transformRadiusToMap(radius)
VISIBLE_RADIUS = UI.projects.foundations.spaces.floatingSpace.transformRadiusToMap(VISIBLE_RADIUS)
} else {
visiblePosition = thisObject.fitFunction(visiblePosition)
}
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = thisObject.payload.floatingObject.fillStyle
browserCanvasContext.fill()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS - 2, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI.projects.foundations.spaces.floatingSpace.style.backgroundColor + ', 1)'
browserCanvasContext.fill()
let schemaDocument = getSchemaDocument(thisObject.payload.node)
if (schemaDocument === undefined) {
console.log('Node ' + thisObject.payload.node + ' without Schema Document at APP SCHEMA.')
return
}
drawOnFocus()
drawHierarchyHeadRing()
drawProjectHeadRing()
drawInfoRing()
drawWarningRing()
drawErrorRing()
drawHighlighted()
drawReadyToChainAttach()
drawAvailableToChainAttach()
drawReadyToReferenceAttach()
drawAvailableToReferenceAttach()
function drawOnFocus() {
if (thisObject.isOnFocus === true) {
/* Black Translucent Background when node is in focus */
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.fillStyle = 'rgba(' + UI.projects.foundations.spaces.floatingSpace.style.backgroundColor + ', 0.70)'
browserCanvasContext.fill()
/* Border when node is in focus */
if (
thisObject.hasError !== true &&
thisObject.WarningError !== true &&
thisObject.hasInfo !== true &&
schemaDocument.isHierarchyHead !== true &&
thisObject.circularProgressBar === undefined
) {
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + 1 + ')'
browserCanvasContext.lineWidth = 3
browserCanvasContext.setLineDash([]) // Resets Line Dash
browserCanvasContext.stroke()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS - 1, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK_TURQUOISE + ', ' + 1 + ')'
browserCanvasContext.lineWidth = 2
browserCanvasContext.setLineDash([]) // Resets Line Dash
browserCanvasContext.stroke()
}
}
}
function drawHierarchyHeadRing() {
/* Hierarchy Head Ring */
if (schemaDocument.isHierarchyHead === true) {
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
if (schemaDocument.inMapMode !== undefined) {
if (schemaDocument.inMapMode.showHierarchyHeadRing === false) {
return
}
}
}
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
VISIBLE_RADIUS = UI.projects.foundations.spaces.floatingSpace.transformRadiusToMap(VISIBLE_RADIUS)
}
let OPACITY = 0.5
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 10
browserCanvasContext.setLineDash([1, 10])
browserCanvasContext.stroke()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 1
if (thisObject.payload.node.isPlugin === true) {
browserCanvasContext.setLineDash([]) // Resets Line Dash
} else {
browserCanvasContext.setLineDash([10, 20])
}
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawProjectHeadRing() {
/* Project Head Ring */
if (schemaDocument.isProjectHead === true) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
VISIBLE_RADIUS = UI.projects.foundations.spaces.floatingSpace.transformRadiusToMap(VISIBLE_RADIUS)
}
let OPACITY = 0.5
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK_TURQUOISE + ', ' + OPACITY + ')'
if (thisObject.payload.floatingObject.isOnFocus === true) {
browserCanvasContext.lineWidth = 30
browserCanvasContext.setLineDash([]) // Resets Line Dash
} else {
browserCanvasContext.lineWidth = 30
browserCanvasContext.setLineDash([1, 3])
}
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawInfoRing() {
/* Info Ring */
if (thisObject.hasInfo === true) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
VISIBLE_RADIUS = UI.projects.foundations.spaces.floatingSpace.transformRadiusToMap(VISIBLE_RADIUS)
}
let OPACITY = infoMessageCounter / 30
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK_TURQUOISE + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 5
browserCanvasContext.setLineDash([2 + infoRingAnimation, 14 - infoRingAnimation])
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawWarningRing() {
/* Warning Ring */
if (thisObject.hasWarning === true) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
VISIBLE_RADIUS = UI.projects.foundations.spaces.floatingSpace.transformRadiusToMap(VISIBLE_RADIUS)
}
let OPACITY = warningMessageCounter / 30
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 5
browserCanvasContext.setLineDash([2 + warningRingAnimation, 14 - warningRingAnimation])
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawErrorRing() {
/* Error Ring */
if (thisObject.hasError === true) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
VISIBLE_RADIUS = UI.projects.foundations.spaces.floatingSpace.transformRadiusToMap(VISIBLE_RADIUS)
}
let OPACITY = errorMessageCounter / 30
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 5
browserCanvasContext.setLineDash([2 + errorRingAnimation, 14 - errorRingAnimation])
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawHighlighted() {
if (isHighlighted === true) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius
let OPACITY = highlightCounter / 10
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 10
browserCanvasContext.setLineDash([4, 20])
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawReadyToChainAttach() {
if (isReadyToChainAttach === true) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius * 2.5 + readyToChainAttachDisplayCounter - readyToChainAttachDisplayCounter / 2
let OPACITY = readyToChainAttachCounter / 10
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 10
browserCanvasContext.setLineDash([10, 90])
browserCanvasContext.stroke()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 5
browserCanvasContext.setLineDash([5, 45])
browserCanvasContext.stroke()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 1
browserCanvasContext.setLineDash([2, 8])
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawAvailableToChainAttach() {
if (isAvailableToChainAttach === true && isReadyToChainAttach === false) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius * 2.5
let OPACITY = availableToChainAttachCounter / 10
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TURQUOISE + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 10
browserCanvasContext.setLineDash([8, 32])
browserCanvasContext.stroke()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TURQUOISE + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 2
browserCanvasContext.setLineDash([3, 5])
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawReadyToReferenceAttach() {
if (isReadyToReferenceAttach === true) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius * 2.5 + readyToReferenceAttachDisplayCounter - readyToReferenceAttachDisplayCounter / 2
let OPACITY = readyToReferenceAttachCounter / 10
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GOLDEN_ORANGE + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 10
browserCanvasContext.setLineDash([10, 90])
browserCanvasContext.stroke()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GOLDEN_ORANGE + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 5
browserCanvasContext.setLineDash([5, 45])
browserCanvasContext.stroke()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GOLDEN_ORANGE + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 1
browserCanvasContext.setLineDash([2, 8])
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
function drawAvailableToReferenceAttach() {
if (isAvailableToReferenceAttach === true && isReadyToReferenceAttach === false) {
VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius * 2.5
let OPACITY = availableToReferenceAttachCounter / 10
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREY + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 10
browserCanvasContext.setLineDash([8, 32])
browserCanvasContext.stroke()
browserCanvasContext.beginPath()
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
browserCanvasContext.closePath()
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREY + ', ' + OPACITY + ')'
browserCanvasContext.lineWidth = 2
browserCanvasContext.setLineDash([3, 5])
browserCanvasContext.stroke()
browserCanvasContext.setLineDash([]) // Resets Line Dash
}
}
}
/* Image */
if (icon !== undefined) {
if (icon.canDrawIcon === true) {
// If this UiObject is being loaded then display at half opacity
if(thisObject.payload.isLoading === true) {
browserCanvasContext.globalAlpha = 0.5
} else {
browserCanvasContext.globalAlpha = 1
}
let additionalImageSize = 0
if (isRunningAtBackend === true || isReadyToReferenceAttach === true || isReadyToChainAttach === true) { additionalImageSize = 20 }
let totalImageSize = additionalImageSize + thisObject.payload.floatingObject.currentImageSize
let schemaDocument = getSchemaDocument(thisObject.payload.node)
if (schemaDocument === undefined) { return }
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
if (schemaDocument.isHierarchyHead === true || schemaDocument.isProjectHead === true) {
totalImageSize = 50
} else {
totalImageSize = 25
totalImageSize = UI.projects.foundations.spaces.floatingSpace.transformImagesizeToMap(totalImageSize)
}
}
if (thisObject.isShowing === true) {
totalImageSize = 50
}
if (UI.projects.foundations.spaces.floatingSpace.inMapMode === true) {
if (schemaDocument.inMapMode !== undefined) {
if (schemaDocument.inMapMode.smallIcon === true) {
totalImageSize = totalImageSize * 0.75
}
}
}
browserCanvasContext.drawImage(
icon, position.x - totalImageSize / 2,
position.y - totalImageSize / 2,
totalImageSize,
totalImageSize)
}
}
if (executingIcon !== undefined) {
if (executingIcon.canDrawIcon === true) {
if (isRunningAtBackend === true) {
const DISTANCE_FROM_CENTER = thisObject.payload.floatingObject.container.frame.radius / 3 + 50
const EXECUTING_ICON_SIZE = 20 + thisObject.payload.floatingObject.container.frame.radius / 6
browserCanvasContext.drawImage(
executingIcon, position.x - EXECUTING_ICON_SIZE / 2,
position.y - EXECUTING_ICON_SIZE / 2 - DISTANCE_FROM_CENTER,
EXECUTING_ICON_SIZE,
EXECUTING_ICON_SIZE)
}
}
}
}
}