diff --git a/ChartingSpace/PlottersManager.js b/ChartingSpace/PlottersManager.js index 458a2599b..5338823ad 100644 --- a/ChartingSpace/PlottersManager.js +++ b/ChartingSpace/PlottersManager.js @@ -271,6 +271,30 @@ function newPlottersManager() { } connector.nodesErrors.onRecordChangeEventsSubscriptionId = connector.plotter.container.eventHandler.listenToEvent('Current Record Changed', connector.nodesErrors.onRecordChange) } + if (plotterModule.nodesWarnings !== undefined && plotterModule.config.connectTo !== undefined) { + connector.nodesWarnings = newNodesWarnings() + switch (plotterModule.config.connectTo) { + case 'Trading System': + connector.nodesWarnings.initialize(tradingSystem) + break + case 'Trading Engine': + connector.nodesWarnings.initialize(tradingEngine) + break + } + connector.nodesWarnings.onRecordChangeEventsSubscriptionId = connector.plotter.container.eventHandler.listenToEvent('Current Record Changed', connector.nodesWarnings.onRecordChange) + } + if (plotterModule.nodesInfos !== undefined && plotterModule.config.connectTo !== undefined) { + connector.nodesInfos = newNodesInfos() + switch (plotterModule.config.connectTo) { + case 'Trading System': + connector.nodesInfos.initialize(tradingSystem) + break + case 'Trading Engine': + connector.nodesInfos.initialize(tradingEngine) + break + } + connector.nodesInfos.onRecordChangeEventsSubscriptionId = connector.plotter.container.eventHandler.listenToEvent('Current Record Changed', connector.nodesInfos.onRecordChange) + } if (plotterModule.nodesRunning !== undefined && plotterModule.config.connectTo !== undefined) { connector.nodesRunning = newNodesRunning() switch (plotterModule.config.connectTo) { @@ -392,6 +416,14 @@ function newPlottersManager() { connector.plotter.container.eventHandler.stopListening(connector.nodesErrors.onRecordChangeEventsSubscriptionId) connector.nodesErrors.finalize() } + if (connector.nodesWarnings !== undefined) { + connector.plotter.container.eventHandler.stopListening(connector.nodesWarnings.onRecordChangeEventsSubscriptionId) + connector.nodesWarnings.finalize() + } + if (connector.nodesInfos !== undefined) { + connector.plotter.container.eventHandler.stopListening(connector.nodesInfos.onRecordChangeEventsSubscriptionId) + connector.nodesInfos.finalize() + } if (connector.nodesStatus !== undefined) { connector.plotter.container.eventHandler.stopListening(connector.nodesStatus.onRecordChangeEventsSubscriptionId) connector.nodesStatus.finalize() diff --git a/FloatingSpace/UiObject.js b/FloatingSpace/UiObject.js index abb67de11..e3cc02d78 100644 --- a/FloatingSpace/UiObject.js +++ b/FloatingSpace/UiObject.js @@ -24,6 +24,8 @@ function newUiObject() { shortcutKey: undefined, isShowing: undefined, hasError: undefined, + hasWarning: undefined, + hasInfo: undefined, run: run, stop: stop, heartBeat: heartBeat, @@ -35,6 +37,10 @@ function newUiObject() { runningAtBackend: runningAtBackend, setErrorMessage: setErrorMessage, resetErrorMessage: resetErrorMessage, + setWarningMessage: setWarningMessage, + resetWarningMessage: resetWarningMessage, + setInfoMessage: setInfoMessage, + resetInfoMessage: resetInfoMessage, setValue: setValue, resetValue: resetValue, setPercentage: setPercentage, @@ -76,6 +82,8 @@ function newUiObject() { let runningAtBackendCounter = 0 let errorMessageCounter = 0 + let warningMessageCounter = 0 + let infoMessageCounter = 0 let hasValue let valueCounter = 0 @@ -109,6 +117,9 @@ function newUiObject() { let isDragging = false let errorMessage = '' + let warningMessage = '' + let infoMessage = '' + let currentValue = 0 let valueMinDecimals = undefined let currentPercentage = '' @@ -327,6 +338,8 @@ function newUiObject() { highlightPhisycs() runningAtBackendPhisycs() errorMessagePhisycs() + warningMessagePhisycs() + infoMessagePhisycs() valuePhisycs() percentagePhisycs() statusPhisycs() @@ -694,6 +707,22 @@ function newUiObject() { } } + function warningMessagePhisycs() { + warningMessageCounter-- + if (warningMessageCounter < 0) { + warningMessageCounter = 0 + thisObject.hasWarning = false + } + } + + function infoMessagePhisycs() { + infoMessageCounter-- + if (infoMessageCounter < 0) { + infoMessageCounter = 0 + thisObject.hasInfo = false + } + } + function valuePhisycs() { valueCounter-- if (valueCounter < 0) { @@ -767,6 +796,76 @@ function newUiObject() { thisObject.hasError = false } + function setWarningMessage(message, duration) { + if (message !== undefined) { + warningMessage = message + 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 + thisObject.hasWarning = false + } + + function setInfoMessage(message, duration) { + if (message !== undefined) { + infoMessage = message + 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 + thisObject.hasInfo = false + } + function setValue(value, counter, minDecimals) { if (value !== undefined) { currentValue = value @@ -837,6 +936,8 @@ function newUiObject() { function run(pEventsServerClient, callBackFunction) { finalizeEventsServerClient() resetErrorMessage() + resetWarningMessage() + resetInfoMessage() resetPercentage() resetValue() resetStatus() @@ -1090,6 +1191,8 @@ function newUiObject() { if (thisObject.isOnFocus === false) { drawBodyAndPicture() drawErrorMessage() + drawWarningMessage() + drawInfoMessage() drawValue() drawPercentage() drawStatus() @@ -1170,6 +1273,8 @@ function newUiObject() { } drawErrorMessage() + drawWarningMessage() + drawInfoMessage() drawValue() drawPercentage() drawStatus() @@ -1389,6 +1494,24 @@ function newUiObject() { function drawErrorMessage() { if (thisObject.hasError === false) { return } + drawMessage(errorMessage) + } + + function drawWarningMessage() { + if (thisObject.hasError === true) { return } + if (thisObject.hasWarning !== true) { return } + drawMessage(warningMessage) + } + + function drawInfoMessage() { + if (thisObject.hasError === true) { return } + if (thisObject.hasWarning === true) { return } + if (thisObject.hasInfo !== true) { return } + drawMessage(infoMessage) + } + + function drawMessage(message) { + if (canvas.floatingSpace.inMapMode === true) { return } @@ -1414,7 +1537,7 @@ function newUiObject() { if (radius > 6) { const MAX_LABEL_LENGTH = 80 - label = errorMessage + label = message if (label !== undefined && label !== null) { if (label.length > MAX_LABEL_LENGTH) { @@ -1695,7 +1818,7 @@ function newUiObject() { let nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition === undefined) { - console.log('Node ' + thisObject.payload.node + ' without Node Definition at APP SCHEMA.') + console.log('Node ' + thisObject.payload.node + ' without Node Definition at APP SCHEMA.') return } @@ -1708,7 +1831,13 @@ function newUiObject() { browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.BLACK + ', 0.70)' browserCanvasContext.fill() /* Border when node is in focus */ - if (thisObject.hasError !== true && nodeDefinition.isHierarchyHead !== true && thisObject.circularProgressBar === undefined) { + if ( + thisObject.hasError !== true && + thisObject.WarningError !== true && + thisObject.hasInfo !== true && + nodeDefinition.isHierarchyHead !== true && + thisObject.circularProgressBar === undefined + ) { browserCanvasContext.beginPath() browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true) browserCanvasContext.closePath() @@ -1757,7 +1886,39 @@ function newUiObject() { browserCanvasContext.stroke() } + /* Info Ring */ + if (thisObject.hasInfo === true) { + VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius + if (canvas.floatingSpace.inMapMode === true) { + VISIBLE_RADIUS = canvas.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([5, 10]) + browserCanvasContext.stroke() + } + /* Warning Ring */ + if (thisObject.hasWarning === true) { + VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius + if (canvas.floatingSpace.inMapMode === true) { + VISIBLE_RADIUS = canvas.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([5, 10]) + browserCanvasContext.stroke() + } + + /* Error Ring */ if (thisObject.hasError === true) { VISIBLE_RADIUS = thisObject.payload.floatingObject.container.frame.radius if (canvas.floatingSpace.inMapMode === true) { diff --git a/Panels/Layer.js b/Panels/Layer.js index 0605b5355..edb0ccba7 100644 --- a/Panels/Layer.js +++ b/Panels/Layer.js @@ -177,7 +177,7 @@ function newLayer() { 'Image->Image Condition->Image Position->Point->' + 'Text->Text Condition->Text Position->Point->Text Formula->Text Style->' + 'Plotter Panel->Javascript Code->Panel Data->Data Formula->' + - 'Nodes Highlights->Nodes Values->Nodes Errors->Nodes Status->Nodes Progress->Nodes Running->Nodes Announcements->Record Values->' + 'Nodes Highlights->Nodes Values->Nodes Errors->Nodes Warnings->Nodes Infos->Nodes Status->Nodes Progress->Nodes Running->Nodes Announcements->Record Values->' thisObject.definition = functionLibraryProtocolNode.getProtocolNode(thisObject.payload.node, false, true, true, false, false, lightingPath) /* Here we validate that we have all the needed information */ diff --git a/Plotting/NodesInfos.js b/Plotting/NodesInfos.js new file mode 100644 index 000000000..2009596aa --- /dev/null +++ b/Plotting/NodesInfos.js @@ -0,0 +1,47 @@ +function newNodesInfos() { + const MODULE_NAME = 'Nodes Infos' + const logger = newWebDebugLog() + logger.fileName = MODULE_NAME + + let thisObject = { + onRecordChange: onRecordChange, + initialize: initialize, + finalize: finalize + } + let hiriarchyMap + return thisObject + + function finalize() { + hiriarchyMap = undefined + } + + function initialize(pRootNode) { + let rootNode = canvas.designSpace.workspace.getHierarchyHeadsById(pRootNode.id) + hiriarchyMap = getHiriarchyMap(rootNode) + } + + function onRecordChange(currentRecord) { + if (currentRecord === undefined) { return } + let array = currentRecord.infos + if (array === undefined) { return } + for (let i = 0; i < array.length; i++) { + let arrayItem = array[i] + let nodeId = arrayItem[0] + let value = arrayItem[1] + applyValue(nodeId, value) + } + } + + function applyValue(nodeId, value) { + if (canvas.chartingSpace.visible !== true) { return } + let node = hiriarchyMap.get(nodeId) + if (node === undefined) { return } + if (node.payload === undefined) { return } + if (node.payload.uiObject === undefined) { return } + if (value === '') { + node.payload.uiObject.resetInfoMessage() + } else { + node.payload.uiObject.setInfoMessage(value) + } + } +} diff --git a/Plotting/NodesWarnings.js b/Plotting/NodesWarnings.js new file mode 100644 index 000000000..8e09ebe08 --- /dev/null +++ b/Plotting/NodesWarnings.js @@ -0,0 +1,47 @@ +function newNodesWarnings() { + const MODULE_NAME = 'Nodes Warnings' + const logger = newWebDebugLog() + logger.fileName = MODULE_NAME + + let thisObject = { + onRecordChange: onRecordChange, + initialize: initialize, + finalize: finalize + } + let hiriarchyMap + return thisObject + + function finalize() { + hiriarchyMap = undefined + } + + function initialize(pRootNode) { + let rootNode = canvas.designSpace.workspace.getHierarchyHeadsById(pRootNode.id) + hiriarchyMap = getHiriarchyMap(rootNode) + } + + function onRecordChange(currentRecord) { + if (currentRecord === undefined) { return } + let array = currentRecord.warnings + if (array === undefined) { return } + for (let i = 0; i < array.length; i++) { + let arrayItem = array[i] + let nodeId = arrayItem[0] + let value = arrayItem[1] + applyValue(nodeId, value) + } + } + + function applyValue(nodeId, value) { + if (canvas.chartingSpace.visible !== true) { return } + let node = hiriarchyMap.get(nodeId) + if (node === undefined) { return } + if (node.payload === undefined) { return } + if (node.payload.uiObject === undefined) { return } + if (value === '') { + node.payload.uiObject.resetWarningMessage() + } else { + node.payload.uiObject.setWarningMessage(value) + } + } +}