diff --git a/Animation.js b/Animation.js index 1e06c4849..cab8a470c 100644 --- a/Animation.js +++ b/Animation.js @@ -144,12 +144,20 @@ function newAnimation () { browserCanvas.height = 1 } - /* Media Recording */ + /* Video Recording */ videoRecorder.physics() - if (areWeRecording === true) { + if (ARE_WE_RECORDING_A_VIDEO === true) { videoRecorder.recordCanvas() } + /* Panorama Recording */ + if (ARE_WE_RECORDING_A_MARKET_PANORAMA === true) { + if (PANORAMA_WAS_PANNED === true) { + addToMarketPanorama() + PANORAMA_WAS_PANNED = false + } + } + /* We request the next frame to be drawn, and stablishing a loop */ /* Use this code for full animation speed. */ @@ -168,6 +176,7 @@ function newAnimation () { } function clearBrowserCanvas () { + if (canWeDraw === false) { return } browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)' browserCanvasContext.clearRect(0, 0, browserCanvas.width, browserCanvas.height) } diff --git a/Canvas.js b/Canvas.js index b13ac359c..af920101a 100644 --- a/Canvas.js +++ b/Canvas.js @@ -3,7 +3,6 @@ let browserCanvasContext // The context of the canvas object. let stepsInitializationCounter = 0 // This counter the initialization steps required to be able to turn off the splash screen. let marketInitializationCounter = 0 // This counter the initialization of markets required to be able to turn off the splash screen. -let splashScreenNeeded = true function newCanvas () { const MODULE_NAME = 'Canvas' @@ -32,12 +31,13 @@ function newCanvas () { let thisObject = { eventHandler: undefined, topSpace: undefined, + sideSpace: undefined, chartingSpace: undefined, floatingSpace: undefined, panelsSpace: undefined, cockpitSpace: undefined, - bottomSpace: undefined, designSpace: undefined, + splashScreen: undefined, animation: undefined, mouse: undefined, shorcutNumbers: new Map(), @@ -47,7 +47,6 @@ function newCanvas () { thisObject.eventHandler = newEventHandler() - let splashScreen let lastContainerMouseOver let lastShortcutKeyRejection @@ -63,6 +62,7 @@ function newCanvas () { function finalize () { try { + thisObject.sideSpace.finalize() thisObject.chartingSpace.finalize() thisObject.floatingSpace.finalize() thisObject.shorcutNumbers = undefined @@ -86,7 +86,7 @@ function newCanvas () { browserCanvas.removeEventListener('keydown', onKeyDown, false) browserCanvas.removeEventListener('keyup', onKeyUp, false) - splashScreen = undefined + thisObject.splashScreen = undefined lastContainerMouseOver = undefined hisObject.mouse = undefined @@ -109,22 +109,22 @@ function newCanvas () { thisObject.topSpace = newTopSpace() thisObject.topSpace.initialize() - thisObject.designSpace = newDesignSpace() - thisObject.designSpace.initialize() - thisObject.cockpitSpace = newCockpitSpace() thisObject.cockpitSpace.initialize() + thisObject.designSpace = newDesignSpace() + thisObject.designSpace.initialize() + thisObject.panelsSpace = newPanelsSpace() thisObject.panelsSpace.initialize() thisObject.chartingSpace = newChartingSpace() thisObject.chartingSpace.initialize() - thisObject.bottomSpace = thisObject.cockpitSpace + thisObject.sideSpace = newSideSpace() + thisObject.sideSpace.initialize() - splashScreen = newSplashScreen() - splashScreen.initialize() + thisObject.splashScreen = newSplashScreen() let animation = newAnimation() animation.initialize() @@ -137,6 +137,7 @@ function newCanvas () { animation.addCallBackFunction('Charting Space Physics', thisObject.chartingSpace.physics) animation.addCallBackFunction('Design Space Physics', thisObject.designSpace.physics) animation.addCallBackFunction('Panels Space Physics', thisObject.panelsSpace.physics) + animation.addCallBackFunction('Side Space Physics', thisObject.sideSpace.physics) /* Spcaces Drawing */ animation.addCallBackFunction('Floating Space Draw', thisObject.floatingSpace.draw) @@ -145,7 +146,8 @@ function newCanvas () { animation.addCallBackFunction('CockpitSpace Draw', thisObject.cockpitSpace.draw) animation.addCallBackFunction('Design Space Draw', thisObject.designSpace.draw) animation.addCallBackFunction('Top Space Draw', thisObject.topSpace.draw) - animation.addCallBackFunction('Splash Screen Draw', splashScreen.draw) + animation.addCallBackFunction('Side Space Draw', thisObject.sideSpace.draw) + animation.addCallBackFunction('Splash Screen Draw', thisObject.splashScreen.draw) animation.start() } catch (err) { if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) } @@ -211,30 +213,35 @@ function newCanvas () { if ((event.ctrlKey === true || event.metaKey === true)) { let constructorParams switch (event.keyCode) { + case 118: { // F7 + downloadPanorama('Superalgos.Market.Panorama') + return + break + } case 119: { // F8 - downloadCanvas('Superalgos.image.capture') + downloadCanvas('Superalgos.Image.Capture', browserCanvas) return break } case 120: { // F9 - constructorParams = { format: 'gif', workersPath: 'externalScripts/', framerate: 8, name: 'Superalgos.video.capture'} + constructorParams = { format: 'gif', workersPath: 'externalScripts/', framerate: 8, name: 'Superalgos.Video.Capture'} break } case 121: { // F10 - constructorParams = { format: 'webm', framerate: 8, name: 'Superalgos.video.capture' } + constructorParams = { format: 'webm', framerate: 8, name: 'Superalgos.Video.Capture' } break } default: return } - if (areWeRecording === false) { + if (ARE_WE_RECORDING_A_VIDEO === false) { console.log('RECORDING', constructorParams.format) mediaRecorder = new CCapture(constructorParams) mediaRecorder.start() - areWeRecording = true + ARE_WE_RECORDING_A_VIDEO = true } else { console.log('SAVING', constructorParams.format) - areWeRecording = false + ARE_WE_RECORDING_A_VIDEO = false mediaRecorder.stop() mediaRecorder.save() } @@ -295,11 +302,7 @@ function newCanvas () { } if (event.shiftKey === true && (event.ctrlKey === true || event.metaKey === true) && (event.key === 'S' || event.key === 's')) { - let saved = canvas.designSpace.workspace.save() - if (saved === true) { - canvas.cockpitSpace.setStatus('Workspace Saved.', 50, canvas.cockpitSpace.statusTypes.ALL_GOOD) - } - + canvas.designSpace.workspace.save() event.preventDefault() return } @@ -578,8 +581,21 @@ function newCanvas () { let container - /* We check if the mouse is over an element of the Design Space / */ + /* We check if the mouse is over an element of the Side Space / */ + container = thisObject.sideSpace.getContainer(point) + if (container !== undefined && container.isDraggeable === true) { + containerBeingDragged = container + containerDragStarted = true + containerBeingDragged.eventHandler.raiseEvent('onDragStarted', point) + return + } + + if (container !== undefined && container.isDraggeable === false) { + return + } + + /* We check if the mouse is over an element of the Design Space / */ container = thisObject.designSpace.getContainer(point) if (container !== undefined && container.isDraggeable === true) { @@ -593,8 +609,7 @@ function newCanvas () { return } - /* We check if the mouse is over an element of the Top Space / */ - + /* We check if the mouse is over an element of the Top Space / */ container = thisObject.topSpace.getContainer(point) if (container !== undefined && container.isDraggeable === true) { @@ -604,8 +619,7 @@ function newCanvas () { return } - /* We check if the mouse is over an element of the CockpitSpace / */ - + /* We check if the mouse is over an element of the CockpitSpace / */ container = thisObject.cockpitSpace.getContainer(point) if (container !== undefined && container.isDraggeable === true) { @@ -620,8 +634,7 @@ function newCanvas () { return } - /* We check if the mouse is over a panel/ */ - + /* We check if the mouse is over a panel/ */ container = thisObject.panelsSpace.getContainer(point, GET_CONTAINER_PURPOSE.DRAGGING) if (container !== undefined && event.shiftKey === false) { @@ -640,8 +653,7 @@ function newCanvas () { return } - /* we check if it is over any of the existing containers at the Charting Space. */ - + /* we check if it is over any of the existing containers at the Charting Space. */ container = thisObject.chartingSpace.getContainer(point, GET_CONTAINER_PURPOSE.DRAGGING) if (container !== undefined) { @@ -698,8 +710,15 @@ function newCanvas () { let container - /* We check if the mouse is over an element of the Design Space / */ + /* We check if the mouse is over an element of the Side Space / */ + container = thisObject.sideSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_CLICK) + if (container !== undefined && container.isClickeable === true) { + container.eventHandler.raiseEvent('onMouseClick', point) + return + } + + /* We check if the mouse is over an element of the Design Space / */ container = thisObject.designSpace.getContainer(point) if (container !== undefined && container.isClickeable === true) { @@ -707,8 +726,7 @@ function newCanvas () { return } - /* We check if the mouse is over an element of the Top Space / */ - + /* We check if the mouse is over an element of the Top Space / */ container = thisObject.topSpace.getContainer(point) if (container !== undefined && container.isClickeable === true) { @@ -716,8 +734,7 @@ function newCanvas () { return } - /* We check if the mouse is over an element of the CockpitSpace / */ - + /* We check if the mouse is over an element of the CockpitSpace / */ container = thisObject.cockpitSpace.getContainer(point) if (container !== undefined && container.isClickeable === true) { @@ -725,8 +742,7 @@ function newCanvas () { return } - /* We check if the mouse is over a panel/ */ - + /* We check if the mouse is over a panel/ */ container = thisObject.panelsSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_CLICK) if (container !== undefined && container.isClickeable === true) { @@ -734,8 +750,7 @@ function newCanvas () { return } - /* If it is not, then we check if it is over any of the existing containers at the Charting Space. */ - + /* If it is not, then we check if it is over any of the existing containers at the Charting Space. */ container = thisObject.chartingSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_CLICK) if (container !== undefined && container.isClickeable === true) { @@ -837,6 +852,16 @@ function newCanvas () { let container + /* We check if the mouse is over an element of the Designe Space / */ + if (thisObject.sideSpace !== undefined) { + container = thisObject.sideSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_OVER) + + if (container !== undefined && container.detectMouseOver === true) { + containerFound() + return + } + } + /* We check if the mouse is over an element of the Designe Space / */ if (thisObject.designSpace !== undefined) { container = thisObject.designSpace.getContainer(point) @@ -934,6 +959,16 @@ function newCanvas () { event.mousePosition = point let container + + /* Side Space */ + container = canvas.sideSpace.getContainer({ x: point.x, y: point.y }) + + if (container !== undefined && container.isWheelable === true) { + container.eventHandler.raiseEvent('onMouseWheel', event) + return false // This instructs the browser not to take the event and scroll the page. + } + + /* Panel Space */ container = canvas.panelsSpace.getContainer({ x: point.x, y: point.y }) if (container !== undefined && container.isWheelable === true) { @@ -941,8 +976,7 @@ function newCanvas () { return false // This instructs the browser not to take the event and scroll the page. } - /* We try the CockpitSpace. */ - + /* We try the CockpitSpace. */ container = canvas.cockpitSpace.getContainer({ x: point.x, y: point.y }) if (container !== undefined && container.isWheelable === true) { @@ -950,8 +984,7 @@ function newCanvas () { return false // This instructs the browser not to take the event and scroll the page. } - /* Charting Space. */ - + /* Charting Space. */ container = canvas.chartingSpace.getContainer({ x: point.x, y: point.y }, GET_CONTAINER_PURPOSE.MOUSE_WHEEL) if (container !== undefined && container.isWheelable === true) { container.eventHandler.raiseEvent('onMouseWheel', event) @@ -963,8 +996,7 @@ function newCanvas () { return false } - /* We try second with floating objects. */ - + /* We try second with floating objects. */ container = canvas.floatingSpace.getContainer({ x: point.x, y: point.y }) if (container !== undefined && container.isWheelable === true) { diff --git a/ChartingSpace/EdgeEditor.js b/ChartingSpace/EdgeEditor.js index 6932fa58b..134d0006f 100644 --- a/ChartingSpace/EdgeEditor.js +++ b/ChartingSpace/EdgeEditor.js @@ -195,9 +195,18 @@ function newEdgeEditor () { } if (event.shiftKey === false && event.ctrlKey === false && event.code === 'ArrowRight') { - onDragStarted(event) - thisObject.container.frame.position.x = thisObject.container.frame.position.x - STEP - whatHappened = 'left or right arrow key pressed' + if (ARE_WE_RECORDING_A_MARKET_PANORAMA === true) { + if (PANORAMA_WAS_PANNED === false) { + PANORAMA_WAS_PANNED = true + onDragStarted(event) + thisObject.container.frame.position.x = thisObject.container.frame.position.x - STEP * 2 + whatHappened = 'left or right arrow key pressed' + } + } else { + onDragStarted(event) + thisObject.container.frame.position.x = thisObject.container.frame.position.x - STEP + whatHappened = 'left or right arrow key pressed' + } return } diff --git a/ChartingSpace/PlottersManager.js b/ChartingSpace/PlottersManager.js index a0002b6fa..e660e48de 100644 --- a/ChartingSpace/PlottersManager.js +++ b/ChartingSpace/PlottersManager.js @@ -99,7 +99,7 @@ function newPlottersManager () { for (let i = 0; i < layer.definition.referenceParent.referenceParent.datasets.length; i++) { let dataset = layer.definition.referenceParent.referenceParent.datasets[i] - switch (dataset.code.type) { + switch (dataset.config.type) { case 'Market Files': { storage.onMarketFileLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('Market File Loaded', layer.onMarketFileLoaded) } @@ -125,8 +125,8 @@ function newPlottersManager () { } } - let baseAsset = layer.definition.referenceParent.parentNode.referenceParent.baseAsset.referenceParent.code.codeName - let quotedAsset = layer.definition.referenceParent.parentNode.referenceParent.quotedAsset.referenceParent.code.codeName + let baseAsset = layer.definition.referenceParent.parentNode.referenceParent.baseAsset.referenceParent.config.codeName + let quotedAsset = layer.definition.referenceParent.parentNode.referenceParent.quotedAsset.referenceParent.config.codeName let market = { baseAsset: baseAsset, quotedAsset: quotedAsset @@ -146,8 +146,8 @@ function newPlottersManager () { } } - let host = layer.networkNode.code.host - let webPort = layer.networkNode.code.webPort + let host = layer.networkNode.config.host + let webPort = layer.networkNode.config.webPort if (host === undefined) { host = 'localhost' } if (webPort === undefined) { webPort = window.location.port } @@ -174,10 +174,10 @@ function newPlottersManager () { /* Now we have all the initial data loaded and ready to be delivered to the new instance of the plotter. */ let plotter - if (plotterModule.code.isLegacy !== true) { + if (plotterModule.config.isLegacy !== true) { plotter = newPlotter() } else { - plotter = getNewPlotter(dataMine.code.codeName, plotterModule.parentNode.code.codeName, plotterModule.code.codeName) + plotter = getNewPlotter(dataMine.config.codeName, plotterModule.parentNode.config.codeName, plotterModule.config.codeName) } plotter.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true) @@ -203,9 +203,9 @@ function newPlottersManager () { let panel = plotterModule.panels[i] let parameters = { - dataMine: dataMine.code.codeName, - plotterCodeName: plotterModule.parentNode.code.codeName, - moduleCodeName: plotterModule.code.codeName, + dataMine: dataMine.config.codeName, + plotterCodeName: plotterModule.parentNode.config.codeName, + moduleCodeName: plotterModule.config.codeName, panelNode: panel } diff --git a/ChartingSpace/Viewport.js b/ChartingSpace/Viewport.js index 4f60172be..5bd837de8 100644 --- a/ChartingSpace/Viewport.js +++ b/ChartingSpace/Viewport.js @@ -369,10 +369,10 @@ function newViewport () { /* Save the zoom at the node config, so that the user can change it if he wishes to. */ try { - let code = JSON.parse(thisObject.payload.node.code) - code.zoom = (thisObject.zoomTargetLevel - MIN_ZOOM_LEVEL) / (MAX_ZOOM_LEVEL - MIN_ZOOM_LEVEL) * 100 - code.zoom = code.zoom.toFixed(2) - thisObject.payload.node.code = JSON.stringify(code) + let config = JSON.parse(thisObject.payload.node.config) + config.zoom = (thisObject.zoomTargetLevel - MIN_ZOOM_LEVEL) / (MAX_ZOOM_LEVEL - MIN_ZOOM_LEVEL) * 100 + config.zoom = config.zoom.toFixed(2) + thisObject.payload.node.config = JSON.stringify(config) } catch (err) { // we ignore errors here since most likely they will be parsing errors. } @@ -383,18 +383,18 @@ function newViewport () { /* Read the zoom level from the node config */ try { - let code = JSON.parse(thisObject.payload.node.code) + let config = JSON.parse(thisObject.payload.node.config) - if (isNaN(code.zoom) || code.zoom === null || code.zoom === undefined) { + if (isNaN(config.zoom) || config.zoom === null || config.zoom === undefined) { saveObjectState() return } - code.zoom = code.zoom / 100 * (MAX_ZOOM_LEVEL - MIN_ZOOM_LEVEL) + MIN_ZOOM_LEVEL - if (code.zoom < MIN_ZOOM_LEVEL) { code.zoom = MIN_ZOOM_LEVEL } - if (code.zoom > MAX_ZOOM_LEVEL) { code.zoom = MAX_ZOOM_LEVEL } + config.zoom = config.zoom / 100 * (MAX_ZOOM_LEVEL - MIN_ZOOM_LEVEL) + MIN_ZOOM_LEVEL + if (config.zoom < MIN_ZOOM_LEVEL) { config.zoom = MIN_ZOOM_LEVEL } + if (config.zoom > MAX_ZOOM_LEVEL) { config.zoom = MAX_ZOOM_LEVEL } - if (code.zoom.toFixed(2) !== thisObject.zoomTargetLevel.toFixed(2)) { - newZoomLevel(code.zoom) + if (config.zoom.toFixed(2) !== thisObject.zoomTargetLevel.toFixed(2)) { + newZoomLevel(config.zoom) } else { saveObjectState() } diff --git a/CockpitSpace/Speedometer.js b/CockpitSpace/Speedometer.js index 12f8cc14e..b2e26df1f 100644 --- a/CockpitSpace/Speedometer.js +++ b/CockpitSpace/Speedometer.js @@ -181,18 +181,6 @@ function newSpeedometer () { /* We put the thisObject.params.VALUE in the middle */ - fontSize = 22 - if (thisObject.params.VALUE > 999) { - fontSize = 18 - } - if (thisObject.params.VALUE > 9999) { - fontSize = 14 - } - if (thisObject.params.VALUE > 99999) { - fontSize = 10 - } - browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY - label = thisObject.params.VALUE if (isNaN(label) === false) { @@ -202,6 +190,22 @@ function newSpeedometer () { if (label === 0) { label = label.toFixed(2) } } + fontSize = 22 + if (label.length > 8) { + fontSize = 18 + } + if (label.length > 10) { + fontSize = 14 + } + if (label.length > 12) { + fontSize = 10 + } + if (label.length > 14) { + fontSize = 8 + } + + browserCanvasContext.font = 'bold ' + fontSize + 'px ' + UI_FONT.PRIMARY + // label = label.substring(0, 6) xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO + 7 diff --git a/DesignSpace/Workspace/FunctionLibraries/CCXTFunctions.js b/DesignSpace/Workspace/FunctionLibraries/CCXTFunctions.js index e89b15e3b..047c4dcf3 100644 --- a/DesignSpace/Workspace/FunctionLibraries/CCXTFunctions.js +++ b/DesignSpace/Workspace/FunctionLibraries/CCXTFunctions.js @@ -44,7 +44,7 @@ function newCCXTFunctions () { if (existingExchange === undefined) { let newExchange = functionLibraryUiObjectsFromNodes.addUIObject(node, 'Crypto Exchange') newExchange.name = exchange.name - newExchange.code = '{ \n\"codeName\": \"' + exchange.id + '\"\n}' + newExchange.config = '{ \n\"codeName\": \"' + exchange.id + '\"\n}' newExchange.payload.floatingObject.collapseToggle() newExchange.exchangeAssets.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180 newExchange.exchangeMarkets.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180 @@ -114,7 +114,7 @@ function newCCXTFunctions () { function addAsset (name) { let newAsseet = functionLibraryUiObjectsFromNodes.addUIObject(node, 'Asset') newAsseet.name = name - newAsseet.code = '{ \n\"codeName\": \"' + name + '\"\n}' + newAsseet.config = '{ \n\"codeName\": \"' + name + '\"\n}' } } } @@ -182,7 +182,7 @@ function newCCXTFunctions () { function addMarket (name, baseAsset, quotedAsset) { let newMarket = functionLibraryUiObjectsFromNodes.addUIObject(node, 'Market') newMarket.name = name - newMarket.code = '{ \n\"codeName\": \"' + name + '\"\n}' + newMarket.config = '{ \n\"codeName\": \"' + name + '\"\n}' newMarket.payload.floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_180 newMarket.payload.floatingObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_050X newMarket.payload.floatingObject.arrangementStyle = ARRANGEMENT_STYLE.CONCAVE diff --git a/DesignSpace/Workspace/FunctionLibraries/ChainAttachDetach.js b/DesignSpace/Workspace/FunctionLibraries/ChainAttachDetach.js index 44dd1e1db..5a75546ab 100644 --- a/DesignSpace/Workspace/FunctionLibraries/ChainAttachDetach.js +++ b/DesignSpace/Workspace/FunctionLibraries/ChainAttachDetach.js @@ -31,11 +31,11 @@ function newChainAttachDetach () { return } default: { - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition (node) if (nodeDefinition !== undefined) { /* Detach from parent */ if (node.payload.parentNode !== undefined) { - let parentNodeDefinition = APP_SCHEMA_MAP.get(node.payload.parentNode.type) + let parentNodeDefinition = getNodeDefinition (node.payload.parentNode) if (parentNodeDefinition !== undefined) { if (parentNodeDefinition.properties !== undefined) { for (let i = 0; i < parentNodeDefinition.properties.length; i++) { @@ -166,13 +166,13 @@ function newChainAttachDetach () { } break default: { - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition (node) if (nodeDefinition !== undefined) { node.payload.parentNode = attachToNode node.payload.chainParent = attachToNode /* Attach to new parent */ if (node.payload.parentNode !== undefined) { - let parentNodeDefinition = APP_SCHEMA_MAP.get(node.payload.parentNode.type) + let parentNodeDefinition = getNodeDefinition (node.payload.parentNode) if (parentNodeDefinition !== undefined) { if (parentNodeDefinition.properties !== undefined) { for (let i = 0; i < parentNodeDefinition.properties.length; i++) { diff --git a/DesignSpace/Workspace/FunctionLibraries/DependenciesFilter.js b/DesignSpace/Workspace/FunctionLibraries/DependenciesFilter.js index 2f88bf30d..1e4fb26ac 100644 --- a/DesignSpace/Workspace/FunctionLibraries/DependenciesFilter.js +++ b/DesignSpace/Workspace/FunctionLibraries/DependenciesFilter.js @@ -14,7 +14,7 @@ function newDependenciesFilter () { function recursiveFilter (node) { filter(node.code) - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition (node) if (nodeDefinition !== undefined) { 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. diff --git a/DesignSpace/Workspace/FunctionLibraries/NodeChildren.js b/DesignSpace/Workspace/FunctionLibraries/NodeChildren.js index 894dd0623..0165b1ecd 100644 --- a/DesignSpace/Workspace/FunctionLibraries/NodeChildren.js +++ b/DesignSpace/Workspace/FunctionLibraries/NodeChildren.js @@ -14,7 +14,7 @@ function newNodeChildren () { childrenCount: 0, childIndex: undefined } - let parentNodeDefinition = APP_SCHEMA_MAP.get(parentNode.type) + let parentNodeDefinition = getNodeDefinition (parentNode) if (parentNodeDefinition !== undefined) { 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. @@ -34,7 +34,7 @@ function newNodeChildren () { } break case 'array': { - let nodeDefinition = APP_SCHEMA_MAP.get(childNode.type) + let nodeDefinition = getNodeDefinition (childNode) if (nodeDefinition !== undefined) { let nodePropertyArray = parentNode[property.name] for (let j = 0; j < nodePropertyArray.length; j++) { diff --git a/DesignSpace/Workspace/FunctionLibraries/NodeCloning.js b/DesignSpace/Workspace/FunctionLibraries/NodeCloning.js index fce49b44f..6de8afad8 100644 --- a/DesignSpace/Workspace/FunctionLibraries/NodeCloning.js +++ b/DesignSpace/Workspace/FunctionLibraries/NodeCloning.js @@ -19,12 +19,13 @@ function newNodeCloning () { function cloneNode (node) { if (node === undefined) { return } - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition(node) if (nodeDefinition !== undefined) { let object = { type: node.type, name: node.name, - code: node.code + code: node.code, + config: node.config } /* Children Nodes */ @@ -71,12 +72,13 @@ function newNodeCloning () { function redirectReferenceParents (node) { if (node === undefined) { return } - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition(node) if (nodeDefinition !== undefined) { let object = { type: node.type, name: node.name, - code: node.code + code: node.code, + config: node.config } /* Children Nodes */ diff --git a/DesignSpace/Workspace/FunctionLibraries/NodeDeleter.js b/DesignSpace/Workspace/FunctionLibraries/NodeDeleter.js index c880ade46..7b17905dc 100644 --- a/DesignSpace/Workspace/FunctionLibraries/NodeDeleter.js +++ b/DesignSpace/Workspace/FunctionLibraries/NodeDeleter.js @@ -29,7 +29,7 @@ function newNodeDeleter () { node.payload.referenceParent.payload.uiObject.isShowing = false } - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition (node) if (nodeDefinition !== undefined) { /* Remove all of its own children nodes. */ if (nodeDefinition.properties !== undefined) { @@ -63,7 +63,7 @@ function newNodeDeleter () { /* Remove node from parent */ if (node.payload !== undefined) { if (node.payload.parentNode !== undefined) { - let parentNodeDefinition = APP_SCHEMA_MAP.get(node.payload.parentNode.type) + let parentNodeDefinition = getNodeDefinition (node.payload.parentNode) if (parentNodeDefinition !== undefined) { if (parentNodeDefinition.properties !== undefined) { for (let i = 0; i < parentNodeDefinition.properties.length; i++) { diff --git a/DesignSpace/Workspace/FunctionLibraries/OnFocus.js b/DesignSpace/Workspace/FunctionLibraries/OnFocus.js index a45c9f76c..21596fb7c 100644 --- a/DesignSpace/Workspace/FunctionLibraries/OnFocus.js +++ b/DesignSpace/Workspace/FunctionLibraries/OnFocus.js @@ -7,7 +7,7 @@ function newOnFocus () { function getNodeThatIsOnFocus (node) { if (node === undefined) { return } if (node.payload === undefined) { return } - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition (node) if (nodeDefinition !== undefined) { /* First we ask the question to ourself */ if (node.payload.uiObject.isOnFocus === true) { diff --git a/DesignSpace/Workspace/FunctionLibraries/ProtocolNode.js b/DesignSpace/Workspace/FunctionLibraries/ProtocolNode.js index 73d626530..a6a533549 100644 --- a/DesignSpace/Workspace/FunctionLibraries/ProtocolNode.js +++ b/DesignSpace/Workspace/FunctionLibraries/ProtocolNode.js @@ -9,17 +9,18 @@ function newProtocolNode () { } return thisObject - function getProtocolNode (node, removePersonalData, parseCode, includeIds, includePayload, includeReferencesInSavedPayload, lightingPath) { + function getProtocolNode (node, removePersonalData, parseConfig, includeIds, includePayload, includeReferencesInSavedPayload, lightingPath) { if (node === undefined) { return } if (node.payload === undefined) { return } - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition(node) if (nodeDefinition !== undefined) { if (removePersonalData === true && nodeDefinition.isPersonalData === true) { return } let object = { type: node.type, name: node.name, - code: node.code + code: node.code, + config: node.config } /* Children Nodes */ @@ -31,11 +32,11 @@ function newProtocolNode () { case 'node': { if (node[property.name] !== undefined) { if (lightingPath === undefined) { - object[property.name] = getProtocolNode(node[property.name], removePersonalData, parseCode, includeIds, includeReferencesInSavedPayload, includePayload) + object[property.name] = getProtocolNode(node[property.name], removePersonalData, parseConfig, includeIds, includeReferencesInSavedPayload, includePayload) } else { let newLightingPath = getNewLightingPath(lightingPath, node.type, property.childType) if (newLightingPath !== undefined) { - object[property.name] = getProtocolNode(node[property.name], removePersonalData, parseCode, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath) + object[property.name] = getProtocolNode(node[property.name], removePersonalData, parseConfig, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath) } } } @@ -47,7 +48,7 @@ function newProtocolNode () { let nodePropertyArray = node[property.name] object[property.name] = [] for (let m = 0; m < nodePropertyArray.length; m++) { - let protocolNode = getProtocolNode(nodePropertyArray[m], removePersonalData, parseCode, includeIds, includeReferencesInSavedPayload, includePayload) + let protocolNode = getProtocolNode(nodePropertyArray[m], removePersonalData, parseConfig, includeIds, includeReferencesInSavedPayload, includePayload) if (protocolNode !== undefined) { object[property.name].push(protocolNode) } @@ -58,7 +59,7 @@ function newProtocolNode () { let nodePropertyArray = node[property.name] object[property.name] = [] for (let m = 0; m < nodePropertyArray.length; m++) { - let protocolNode = getProtocolNode(nodePropertyArray[m], removePersonalData, parseCode, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath) + let protocolNode = getProtocolNode(nodePropertyArray[m], removePersonalData, parseConfig, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath) if (protocolNode !== undefined) { object[property.name].push(protocolNode) } @@ -76,25 +77,25 @@ function newProtocolNode () { if (node.payload.parentNode !== undefined) { let newLightingPath = getNewLightingPath(lightingPath, node.type, node.payload.parentNode.type) if (newLightingPath !== undefined) { - object.parentNode = getProtocolNode(node.payload.parentNode, removePersonalData, parseCode, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath) + object.parentNode = getProtocolNode(node.payload.parentNode, removePersonalData, parseConfig, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath) } } if (node.payload.referenceParent !== undefined) { let newLightingPath = getNewLightingPath(lightingPath, node.type, node.payload.referenceParent.type) if (newLightingPath !== undefined) { - object.referenceParent = getProtocolNode(node.payload.referenceParent, removePersonalData, parseCode, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath) + object.referenceParent = getProtocolNode(node.payload.referenceParent, removePersonalData, parseConfig, includeIds, includePayload, includeReferencesInSavedPayload, newLightingPath) } } - if (parseCode && object.code !== undefined && nodeDefinition.editors !== undefined) { + if (parseConfig && object.config !== undefined && nodeDefinition.editors !== undefined) { if (nodeDefinition.editors.config === true) { try { - object.code = JSON.parse(node.code) + object.config = JSON.parse(node.config) } catch (err) { if (ERROR_LOG === true) { logger.write('[ERROR] getProtocolNode -> default -> err = ' + err.stack) } if (ERROR_LOG === true) { logger.write('[ERROR] getProtocolNode -> default -> node.type = ' + node.type) } if (ERROR_LOG === true) { logger.write('[ERROR] getProtocolNode -> default -> node.name = ' + node.name) } - if (ERROR_LOG === true) { logger.write('[ERROR] getProtocolNode -> default -> node.code = ' + node.code) } + if (ERROR_LOG === true) { logger.write('[ERROR] getProtocolNode -> default -> node.config = ' + node.config) } if (ERROR_LOG === true) { logger.write('[ERROR] getProtocolNode -> default -> node.id = ' + node.id) } } } diff --git a/DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js b/DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js index e1f7883e2..41b4da779 100644 --- a/DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js +++ b/DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js @@ -6,7 +6,7 @@ function newSessionFunctions () { return thisObject - function runSession (node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, callBackFunction) { + function runSession (node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, resume, callBackFunction) { if (validations(node) !== true) { callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) return @@ -37,7 +37,28 @@ function newSessionFunctions () { 'Close Stage->Close Execution->' + 'Announcement->Formula->' - let tradingSystem = functionLibraryProtocolNode.getProtocolNode(node.payload.referenceParent, false, true, true, false, false, lightingPath) + let tradingSystem = functionLibraryProtocolNode.getProtocolNode(node.tradingSystemReference.payload.referenceParent, false, true, true, false, false, lightingPath) + + lightingPath = '' + + 'Trading Engine->' + + 'Episode->Current->Last->Previous->' + + 'Episode Counters->Episode Statistics->' + + 'Periods->Positions->Hits->Fails->' + + 'Profit Loss->Hit Ratio->Days->ROI->Anualized Rate Of Return->User Defined Statistic->' + + 'Formula->' + + 'Balance->Base Asset->Quoted Asset->' + + 'Distance To Event->' + + 'Trigger On->Trigger Off->Take Position->Close Position->Next Phase->Move To Phase->' + + 'Strategy->' + + 'Begin->End->Strategy Name->Index->Stage Type->Status->Begin Rate->End Rate->Situation Name->' + + 'Strategy Counters->Periods->' + + 'Position->' + + 'Begin->End->Rate->Size->Exit Type->Status->Begin Rate->End Rate->Situation Name->' + + 'Position Counters->Periods->' + + 'Position Statistics->Days->ROI->User Defined Statistic->' + + 'Formula' + + let tradingEngine = functionLibraryProtocolNode.getProtocolNode(node.tradingEngineReference.payload.referenceParent, false, true, true, false, false, lightingPath) lightingPath = '' + 'Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->' + @@ -48,13 +69,16 @@ function newSessionFunctions () { let session = functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath) - let dependencyFilter = functionLibraryDependenciesFilter.createFilter(node.payload.referenceParent) + let dependencyFilter = functionLibraryDependenciesFilter.createFilter(node.tradingSystemReference.payload.referenceParent) /* Raise event to run the session */ let event = { + appSchema: JSON.stringify(APP_SCHEMA_ARRAY), session: JSON.stringify(session), tradingSystem: JSON.stringify(tradingSystem), - dependencyFilter: JSON.stringify(dependencyFilter) + tradingEngine: JSON.stringify(tradingEngine), + dependencyFilter: JSON.stringify(dependencyFilter), + resume: resume } eventsServerClient.raiseEvent(key, 'Run Session', event) @@ -121,8 +145,23 @@ function newSessionFunctions () { return } - if (node.payload.referenceParent === undefined) { - node.payload.uiObject.setErrorMessage('Session needs to reference a Trading System.') + if (node.tradingSystemReference === undefined) { + node.payload.uiObject.setErrorMessage('Session needs a child Trading System Reference.') + return + } + + if (node.tradingEngineReference === undefined) { + node.payload.uiObject.setErrorMessage('Session needs a child Trading Engine Reference.') + return + } + + if (node.tradingSystemReference.payload.referenceParent === undefined) { + node.payload.uiObject.setErrorMessage('Trading System Reference needs to reference a Trading System.') + return + } + + if (node.tradingEngineReference.payload.referenceParent === undefined) { + node.payload.uiObject.setErrorMessage('Trading Engine Reference needs to reference a Trading Engine.') return } return true diff --git a/DesignSpace/Workspace/FunctionLibraries/ShortcutKeys.js b/DesignSpace/Workspace/FunctionLibraries/ShortcutKeys.js index 28e6afc2a..2cd449769 100644 --- a/DesignSpace/Workspace/FunctionLibraries/ShortcutKeys.js +++ b/DesignSpace/Workspace/FunctionLibraries/ShortcutKeys.js @@ -6,7 +6,7 @@ function newShortcutKeys () { function getNodeByShortcutKey (node, searchingKey) { if (node === undefined) { return } - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition (node) if (nodeDefinition !== undefined) { /* Check Self first */ if (node.payload.uiObject.shortcutKey === searchingKey) { diff --git a/DesignSpace/Workspace/FunctionLibraries/SuperScripts.js b/DesignSpace/Workspace/FunctionLibraries/SuperScripts.js index 3965fe328..e8e6b8a90 100644 --- a/DesignSpace/Workspace/FunctionLibraries/SuperScripts.js +++ b/DesignSpace/Workspace/FunctionLibraries/SuperScripts.js @@ -18,7 +18,7 @@ function newSuperScriptsFunctions () { if (exchange === undefined) { functionLibraryUiObjectsFromNodes.createUiObjectFromNode(templateClone, target, target) } else { - let definition = APP_SCHEMA_MAP.get(target.type) + let definition = getNodeDefinition (target) for (let i = 0; i < definition.properties.length; i++) { let property = definition.properties[i] if (property.childType === exchangeNodeType) { diff --git a/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js b/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js index d6253f558..c852cb93f 100644 --- a/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js +++ b/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js @@ -1,5 +1,7 @@ function newUiObjectsFromNodes () { thisObject = { + runTasks: runTasks, + runSessions: runSessions, recreateWorkspace: recreateWorkspace, tryToConnectChildrenWithReferenceParents: tryToConnectChildrenWithReferenceParents, createUiObjectFromNode: createUiObjectFromNode, @@ -14,7 +16,7 @@ function newUiObjectsFromNodes () { return thisObject - function recreateWorkspace (node, replacingCurrentWorkspace) { + function recreateWorkspace (node, callBackFunction) { mapOfNodes = new Map() tasksToRun = [] sessionsToRun = [] @@ -22,16 +24,16 @@ function newUiObjectsFromNodes () { addIncludedNodes() function addIncludedNodes () { - blobService = newFileStorage() + let blobService = newFileStorage() - // if (node.code === undefined) { - node.code = '{ \n"includeDataMines": ["Masters", "Sparta", "TradingEngines"],\n"includeTradingSystems": ["Sparta-WHB-BTC-USDT", "Example-ETH-USDT", "Sparta-BRR-BTC-USDT"],\n"includeSuperScripts": ["Masters"]\n }' + // if (node.config === undefined) { + node.config = '{ \n"includeDataMines": ["Masters", "Sparta", "Masters-Trading"],\n"includeTradingSystems": ["Sparta-WHB-BTC-USDT", "Example-ETH-USDT", "Sparta-BRR-BTC-USDT"],\n"includeSuperScripts": ["Masters"]\n }' // } - let code = JSON.parse(node.code) - let includeDataMines = code.includeDataMines - let includeTradingSystems = code.includeTradingSystems - let includeSuperScripts = code.includeSuperScripts + let config = JSON.parse(node.config) + let includeDataMines = config.includeDataMines + let includeTradingSystems = config.includeTradingSystems + let includeSuperScripts = config.includeSuperScripts let totalIncluded = 0 @@ -47,9 +49,9 @@ function newUiObjectsFromNodes () { for (let i = 0; i < node.rootNodes.length; i++) { let rootNode = node.rootNodes[i] if (rootNode.type === 'Data Mine') { - if (rootNode.code !== undefined) { - let code = JSON.parse(rootNode.code) - if (code.name === name) { + if (rootNode.config !== undefined) { + let config = JSON.parse(rootNode.config) + if (config.name === name) { rootNodes.splice(i, 1) } } @@ -76,9 +78,9 @@ function newUiObjectsFromNodes () { for (let i = 0; i < node.rootNodes.length; i++) { let rootNode = node.rootNodes[i] if (rootNode.type === 'Trading System') { - if (rootNode.code !== undefined) { - let code = JSON.parse(rootNode.code) - if (code.name === name) { + if (rootNode.config !== undefined) { + let config = JSON.parse(rootNode.config) + if (config.name === name) { rootNodes.splice(i, 1) } } @@ -105,9 +107,9 @@ function newUiObjectsFromNodes () { for (let i = 0; i < node.rootNodes.length; i++) { let rootNode = node.rootNodes[i] if (rootNode.type === 'Super Scripts') { - if (rootNode.code !== undefined) { - let code = JSON.parse(rootNode.code) - if (code.name === name) { + if (rootNode.config !== undefined) { + let config = JSON.parse(rootNode.config) + if (config.name === name) { rootNodes.splice(i, 1) } } @@ -135,15 +137,8 @@ function newUiObjectsFromNodes () { tryToConnectChildrenWithReferenceParents() - if (replacingCurrentWorkspace === true) { - // We need to wait all tasks that were potentially running to stop - setTimeout(runTasks, 70000) - // We give a few seconds for the tasks to start - setTimeout(runSessions, 80000) - } else { - runTasks() - // We give a few seconds for the tasks to start - setTimeout(runSessions, 10000) + if (callBackFunction !== undefined) { + callBackFunction() // The recreation of the workspace is complete } } } @@ -184,10 +179,33 @@ function newUiObjectsFromNodes () { } } + function migrateCodeToConfig (node, nodeDefinition) { + /* Code needed to Migrante from Beta 5 to Beta a Workspace */ + if (nodeDefinition.editors !== undefined) { + if (nodeDefinition.editors.config === true) { + if (node.code !== undefined) { + node.config = node.code + node.code = undefined + } + } + } + } + function createUiObjectFromNode (node, parentNode, chainParent, positionOffset) { + /* Code needed to Migrante from Beta 5 to Beta 6 a Trading System + if (node.type === 'Take Profit') { + node.type = 'Managed Take Profit' + } + if (node.type === 'Stop') { + node.type = 'Managed Stop Loss' + } + */ + /* Get node definition */ - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition(node) if (nodeDefinition !== undefined) { + migrateCodeToConfig(node, nodeDefinition) + /* Resolve Initial Values */ if (nodeDefinition.initialValues !== undefined) { if (nodeDefinition.initialValues.code !== undefined) { @@ -195,12 +213,17 @@ function newUiObjectsFromNodes () { node.code = nodeDefinition.initialValues.code } } + if (nodeDefinition.initialValues.config !== undefined) { + if (node.config === undefined) { + node.config = nodeDefinition.initialValues.config + } + } } /* For the cases where an node is not chained to its parent but to the one at the parent before it at its collection */ if (nodeDefinition.chainedToSameType === true) { if (parentNode !== undefined) { - let parentNodeDefinition = APP_SCHEMA_MAP.get(parentNode.type) + let parentNodeDefinition = getNodeDefinition(parentNode) if (parentNodeDefinition !== undefined) { if (parentNodeDefinition.properties !== undefined) { for (let i = 0; i < parentNodeDefinition.properties.length; i++) { @@ -268,12 +291,12 @@ function newUiObjectsFromNodes () { type: type } - let parentNodeDefinition = APP_SCHEMA_MAP.get(parentNode.type) + let parentNodeDefinition = getNodeDefinition(parentNode) if (parentNodeDefinition === undefined) { console.log('Cannot addUIOBject from parent of ' + type + ' because that type it is not defined at the APP_SCHEMA.') } /* Resolve Initial Values */ - let nodeDefinition = APP_SCHEMA_MAP.get(object.type) + let nodeDefinition = getNodeDefinition(object) if (nodeDefinition === undefined) { console.log('Cannot addUIOBject of ' + type + ' because that type it is not defined at the APP_SCHEMA.') @@ -284,6 +307,11 @@ function newUiObjectsFromNodes () { object.code = nodeDefinition.initialValues.code } } + if (nodeDefinition.initialValues !== undefined) { + if (nodeDefinition.initialValues.config !== undefined) { + object.config = nodeDefinition.initialValues.config + } + } if (nodeDefinition.isHierarchyHead === true) { parentNode.rootNodes.push(object) @@ -326,6 +354,9 @@ function newUiObjectsFromNodes () { if (nodeDefinition.initialValues.code !== undefined) { object.code = nodeDefinition.initialValues.code } + if (nodeDefinition.initialValues.config !== undefined) { + object.config = nodeDefinition.initialValues.config + } } } @@ -398,7 +429,7 @@ function newUiObjectsFromNodes () { } function addMissingChildren (node) { - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition(node) /* Connect to Parent */ if (nodeDefinition.properties !== undefined) { diff --git a/DesignSpace/Workspace/Workspace.js b/DesignSpace/Workspace/Workspace.js index 3b1a4891e..4882502b8 100644 --- a/DesignSpace/Workspace/Workspace.js +++ b/DesignSpace/Workspace/Workspace.js @@ -11,6 +11,7 @@ function newWorkspace () { enabled: false, nodeChildren: undefined, eventsServerClients: new Map(), + replaceWorkspaceByLoadingOne: replaceWorkspaceByLoadingOne, save: saveWorkspace, getHierarchyHeads: getHierarchyHeads, getNodeThatIsOnFocus: getNodeThatIsOnFocus, @@ -68,7 +69,7 @@ function newWorkspace () { let workingAtTask = 0 let circularProgressBar = newBusyProgressBar() circularProgressBar.fitFunction = canvas.floatingSpace.fitIntoVisibleArea - let droppedNode + let loadedWorkspaceNode let sessionTimestamp = (new Date()).valueOf() window.localStorage.setItem('Session Timestamp', sessionTimestamp) @@ -85,24 +86,56 @@ function newWorkspace () { function initialize () { try { - let reset = window.localStorage.getItem('Reset') - let savedWorkspace = window.localStorage.getItem(CANVAS_APP_NAME + '.' + 'Workspace') + let lastUsedWorkspace = window.localStorage.getItem('Last Used Workspace') - if (savedWorkspace === null || reset !== null) { - thisObject.workspaceNode = getWorkspace() + if (lastUsedWorkspace !== 'undefined' && lastUsedWorkspace !== null && lastUsedWorkspace !== undefined) { + let blobService = newFileStorage() + blobService.getFileFromHost('LoadWorkspace' + '/' + lastUsedWorkspace, onFileReceived, true) + function onFileReceived (err, text, response) { + if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + canvas.cockpitSpace.setStatus('Could not load the last Workspace used, called "' + lastUsedWorkspace + '". Will switch to the default Workspace instead.', 500, canvas.cockpitSpace.statusTypes.WARNING) + thisObject.workspaceNode = getWorkspace() // This is the default workspace that comes with the system. + recreateWorkspace() + return + } + thisObject.workspaceNode = JSON.parse(text) + recreateWorkspace() + } } else { - thisObject.workspaceNode = JSON.parse(savedWorkspace) + thisObject.workspaceNode = getWorkspace() // This is the default workspace that comes with the system. + recreateWorkspace() } - functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode) - setupEventsServerClients() - thisObject.enabled = true - setInterval(saveWorkspace, 60000) + function recreateWorkspace () { + functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode, finishInitialization) + } + + function finishInitialization () { + setupEventsServerClients() + runTasksAndSessions(false) + thisObject.enabled = true + canvas.cockpitSpace.initializePosition() + canvas.splashScreen.initialize() + setInterval(saveWorkspace, 60000) + } } catch (err) { if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) } } } + function runTasksAndSessions (replacingCurrentWorkspace) { + if (replacingCurrentWorkspace === true) { + // We need to wait all tasks that were potentially running to stop + setTimeout(functionLibraryUiObjectsFromNodes.runTasks, 70000) + // We give a few seconds for the tasks to start + setTimeout(functionLibraryUiObjectsFromNodes.runSessions, 80000) + } else { + functionLibraryUiObjectsFromNodes.runTasks() + // We give a few seconds for the tasks to start + setTimeout(functionLibraryUiObjectsFromNodes.runSessions, 10000) + } + } + function setupEventsServerClients () { for (let i = 0; i < thisObject.workspaceNode.rootNodes.length; i++) { let rootNode = thisObject.workspaceNode.rootNodes[i] @@ -115,9 +148,9 @@ function newWorkspace () { let webSocketsPort /* At this point the node does not have the payload property yet, that is why we have to do this manually */ try { - let code = JSON.parse(networkNode.code) - host = code.host - webSocketsPort = code.webSocketsPort + let config = JSON.parse(networkNode.config) + host = config.host + webSocketsPort = config.webSocketsPort } catch (err) { console.log('[ERROR] networkNode ' + networkNode.name + ' has an invalid configuration. Cannot know the host name and webSocketsPort.') return @@ -170,6 +203,23 @@ function newWorkspace () { let textToSave = stringifyWorkspace() window.localStorage.setItem(CANVAS_APP_NAME + '.' + 'Workspace', textToSave) window.localStorage.setItem('Session Timestamp', sessionTimestamp) + + if (workspace.name !== undefined) { + let url = 'SaveWorkspace/' + workspace.name + callServer(textToSave, url, onResponse) + } + + function onResponse (err) { + if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result) { + window.localStorage.setItem('Last Used Workspace', workspace.name) + window.localStorage.setItem('Session Timestamp', sessionTimestamp) + if (ARE_WE_RECORDING_A_MARKET_PANORAMA === false) { + canvas.cockpitSpace.setStatus(workspace.name + ' Saved.', 50, canvas.cockpitSpace.statusTypes.ALL_GOOD) + } + } else { + canvas.cockpitSpace.setStatus('Could not save the Workspace at the Backend. Please check the Backend Console for more information.', 150, canvas.cockpitSpace.statusTypes.WARNING) + } + } return true } } @@ -203,13 +253,14 @@ function newWorkspace () { workingAtTask++ break case 3: - thisObject.workspaceNode = droppedNode - droppedNode = undefined + thisObject.workspaceNode = loadedWorkspaceNode + loadedWorkspaceNode = undefined workingAtTask++ break case 4: - functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode, true) + functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode) setupEventsServerClients() + runTasksAndSessions(true) workingAtTask++ break case 5: @@ -294,7 +345,7 @@ function newWorkspace () { let nodes = [] for (let i = 0; i < thisObject.workspaceNode.rootNodes.length; i++) { let rootNode = thisObject.workspaceNode.rootNodes[i] - let nodeDefinition = APP_SCHEMA_MAP.get(rootNode.type) + let nodeDefinition = getNodeDefinition(rootNode) if (nodeDefinition !== undefined) { if (nodeDefinition.isHierarchyHead === true) { nodes.push(rootNode) @@ -304,6 +355,30 @@ function newWorkspace () { return nodes } + function replaceWorkspaceByLoadingOne (name) { + let blobService = newFileStorage() + blobService.getFileFromHost('LoadWorkspace' + '/' + name, onFileReceived, true) + function onFileReceived (err, text, response) { + if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + canvas.cockpitSpace.setStatus('Could not load the Workspace called "' + name + '". ', 500, canvas.cockpitSpace.statusTypes.WARNING) + return + } + + loadedWorkspaceNode = JSON.parse(text) + saveWorkspace() + canvas.cockpitSpace.toTop() + + let position = { + x: browserCanvas.width / 2, + y: browserCanvas.height / 2 + } + + circularProgressBar.initialize(position) + circularProgressBar.visible = true + workingAtTask = 1 + } + } + function spawn (nodeText, mousePointer) { try { let point = { @@ -314,9 +389,10 @@ function newWorkspace () { spawnPosition.x = point.x spawnPosition.y = point.y - droppedNode = JSON.parse(nodeText) + let droppedNode = JSON.parse(nodeText) if (droppedNode.type === 'Workspace') { + loadedWorkspaceNode = droppedNode circularProgressBar.initialize(mousePointer) circularProgressBar.visible = true workingAtTask = 1 @@ -485,7 +561,12 @@ function newWorkspace () { break case 'Run Session': { - functionLibrarySessionFunctions.runSession(payload.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, callBackFunction) + functionLibrarySessionFunctions.runSession(payload.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, false, callBackFunction) + } + break + case 'Resume Session': + { + functionLibrarySessionFunctions.runSession(payload.node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, true, callBackFunction) } break case 'Stop Session': @@ -508,9 +589,19 @@ function newWorkspace () { referenceDetachNode(payload.node) } break + case 'Push Code to Javascript Code': + { + payload.node.javascriptCode.code = payload.node.code + } + break + case 'Fetch Code to Javascript Code': + { + payload.node.code = payload.node.javascriptCode.code + } + break case 'Open Documentation': { - let definition = APP_SCHEMA_MAP.get(payload.node.type) + let definition = getNodeDefinition(payload.node) if (definition !== undefined) { if (definition.docURL !== undefined) { let newTab = window.open(definition.docURL, '_blank') diff --git a/FloatingSpace/ConditionEditor.js b/FloatingSpace/ConditionEditor.js index f0b2cbef7..5b22ff07e 100644 --- a/FloatingSpace/ConditionEditor.js +++ b/FloatingSpace/ConditionEditor.js @@ -25,12 +25,26 @@ function newConditionEditor () { thisObject.container.isDraggeable = false thisObject.container.detectMouseOver = false thisObject.container.frame.radius = 750 + thisObject.container.frame.width = thisObject.container.frame.radius * 2 + thisObject.container.frame.height = thisObject.container.frame.radius * 2 thisObject.container.frame.containerName = MODULE_NAME let isMouseOver = false let conditionStructure let scanResult + let timeFrameIcon + let dataMineIcon + let botIcon + let whenIcon + let productIcon + let propertyIcon + let operationIcon + let valueIcon + + const PICKER_WIDTH = 150 + const PICKER_HEIGHT = 60 + return thisObject function finalize () { @@ -41,10 +55,26 @@ function newConditionEditor () { conditionStructure = undefined scanResult = undefined + + timeFrameIcon = undefined + dataMineIcon = undefined + whenIcon = undefined + botIcon = undefined + productIcon = undefined + operationIcon = undefined + propertyIcon = undefined + valueIcon = undefined } function initialize () { - + timeFrameIcon = canvas.designSpace.iconCollection.get('time-period') + dataMineIcon = canvas.designSpace.iconCollection.get('data-mine') + botIcon = canvas.designSpace.iconCollection.get('bot-indicator') + whenIcon = canvas.designSpace.iconCollection.get('chronometer') + productIcon = canvas.designSpace.iconCollection.get('product-definition') + propertyIcon = canvas.designSpace.iconCollection.get('record-property') + operationIcon = canvas.designSpace.iconCollection.get('headphones') + valueIcon = canvas.designSpace.iconCollection.get('competition') } function activate (payload) { @@ -53,8 +83,8 @@ function newConditionEditor () { thisObject.payload.uiObject.setErrorMessage('', 0) conditionStructure = { - code: thisObject.payload.node.code, - orOperands: [] + code: '', + logicOperands: [] } scanDataMines() @@ -75,77 +105,84 @@ function newConditionEditor () { } function loadFromCode () { - if (thisObject.payload.node.code === undefined || thisObject.payload.node.code === '') { return } + if (thisObject.payload.node.code === undefined) { thisObject.payload.node.code = '' } + conditionStructure.code = thisObject.payload.node.code.replace(/ /g, '') /* LOGICAL ORs */ - let orArray = conditionStructure.code.split(' || ') - for (let j = 0; j < orArray.length; j++) { + let orArray = conditionStructure.code.split('||') + for (let j = 0; j < 3; j++) { let logicOperand = { code: orArray[j], index: j, - comparison: {} + comparison: {}, + visible: false } + + if (logicOperand.code !== undefined) { + logicOperand.visible = true + if (orArray[j + 1] !== undefined) { + logicOperand.operator = '||' + } + } else { + logicOperand.code = '' + } + checkComparison(logicOperand, j) - conditionStructure.orOperands.push(logicOperand) + conditionStructure.logicOperands.push(logicOperand) } function checkComparison (logicOperand) { /* We are going to decompose the code into 2 comparison operators */ - logicOperand.comparison.operandA = { index: 0} - logicOperand.comparison.operandB = { index: 1} + logicOperand.comparison.operandA = { + index: 0, + code: '' + } + logicOperand.comparison.operandB = { + index: 1, + code: '' + } - if (logicOperand.code.indexOf(' > ') > 0) { - let codeArray = logicOperand.code.split(' > ') + if (logicOperand.code.indexOf('>') > 0) { + let codeArray = logicOperand.code.split('>') logicOperand.comparison.operandA.code = codeArray[0] logicOperand.comparison.operandB.code = codeArray[1] - logicOperand.comparison.operator = ' > ' + logicOperand.comparison.operator = '>' logicOperand.comparison.operatorIndex = 0 } - if (logicOperand.code.indexOf(' < ') > 0) { - let codeArray = logicOperand.code.split(' < ') + if (logicOperand.code.indexOf('<') > 0) { + let codeArray = logicOperand.code.split('<') logicOperand.comparison.operandA.code = codeArray[0] logicOperand.comparison.operandB.code = codeArray[1] - logicOperand.comparison.operator = ' < ' + logicOperand.comparison.operator = '<' logicOperand.comparison.operatorIndex = 1 } - if (logicOperand.code.indexOf(' >= ') > 0) { - let codeArray = logicOperand.code.split(' >= ') + if (logicOperand.code.indexOf('>=') > 0) { + let codeArray = logicOperand.code.split('>=') logicOperand.comparison.operandA.code = codeArray[0] logicOperand.comparison.operandB.code = codeArray[1] - logicOperand.comparison.operator = ' >= ' + logicOperand.comparison.operator = '>=' logicOperand.comparison.operatorIndex = 2 } - if (logicOperand.code.indexOf(' <= ') > 0) { - let codeArray = logicOperand.code.split(' <= ') + if (logicOperand.code.indexOf('<=') > 0) { + let codeArray = logicOperand.code.split('<=') logicOperand.comparison.operandA.code = codeArray[0] logicOperand.comparison.operandB.code = codeArray[1] - logicOperand.comparison.operator = ' <= ' + logicOperand.comparison.operator = '<=' logicOperand.comparison.operatorIndex = 3 } - if (logicOperand.code.indexOf(' === ') > 0) { - let codeArray = logicOperand.code.split(' === ') + if (logicOperand.code.indexOf('===') > 0) { + let codeArray = logicOperand.code.split('===') logicOperand.comparison.operandA.code = codeArray[0] logicOperand.comparison.operandB.code = codeArray[1] - logicOperand.comparison.operator = ' === ' + logicOperand.comparison.operator = '===' logicOperand.comparison.operatorIndex = 4 } - logicOperand.comparison.picker = newPicker() - let picker = logicOperand.comparison.picker - picker.name = 'Comparison' - picker.container.connectToParent(thisObject.container) - picker.container.frame.position.x = 0 - picker.container.frame.width / 2 - picker.container.frame.position.y = 0 - picker.container.frame.height / 2 - let optionsList = ['Greater Than', 'Less Than', 'Greater or Equal Than', 'Less or Equal Than', 'Equal To'] - picker.initialize(optionsList) - - picker.eventSuscriptionId = picker.container.eventHandler.listenToEvent('onParentChanged', onParentChanged) - - /* Each comparison code may have one or more algebraic operators */ + /* Each comparison code may have one or more algebra operators */ checkAlgebra(logicOperand, logicOperand.comparison.operandA) checkAlgebra(logicOperand, logicOperand.comparison.operandB) } @@ -156,114 +193,205 @@ function newConditionEditor () { operandB: { index: 1} } - /* The default situation is that there is no Algebraic operation, meaning we will setup a Algebraic operation only with operandA */ + /* The default situation is that there is no algebra operation, meaning we will setup a algebra operation only with operandA */ comparisonOperand.algebra.operandA.code = comparisonOperand.code comparisonOperand.algebra.operandB.code = '' - comparisonOperand.algebra.operator = ' ... ' + comparisonOperand.algebra.operator = '...' comparisonOperand.algebra.operatorIndex = 0 - if (comparisonOperand.code.indexOf(' + ') > 0) { - let codeArray = logicOperand.code.split(' + ') + if (comparisonOperand.code.indexOf('+') > 0) { + let codeArray = comparisonOperand.code.split('+') comparisonOperand.algebra.operandA.code = codeArray[0] comparisonOperand.algebra.operandB.code = codeArray[1] - comparisonOperand.algebra.operator = ' + ' + comparisonOperand.algebra.operator = '+' comparisonOperand.algebra.operatorIndex = 1 } - if (comparisonOperand.code.indexOf(' - ') > 0) { - let codeArray = logicOperand.code.split(' - ') + if (comparisonOperand.code.indexOf('-') > 0) { + let codeArray = comparisonOperand.code.split('-') comparisonOperand.algebra.operandA.code = codeArray[0] comparisonOperand.algebra.operandB.code = codeArray[1] - comparisonOperand.algebra.operator = ' - ' + comparisonOperand.algebra.operator = '-' comparisonOperand.algebra.operatorIndex = 2 } - if (comparisonOperand.code.indexOf(' * ') > 0) { - let codeArray = logicOperand.code.split(' * ') + if (comparisonOperand.code.indexOf('*') > 0) { + let codeArray = comparisonOperand.code.split('*') comparisonOperand.algebra.operandA.code = codeArray[0] comparisonOperand.algebra.operandB.code = codeArray[1] - comparisonOperand.algebra.operator = ' * ' + comparisonOperand.algebra.operator = '*' comparisonOperand.algebra.operatorIndex = 3 } - if (comparisonOperand.code.indexOf(' / ') > 0) { - let codeArray = logicOperand.code.split(' / ') + if (comparisonOperand.code.indexOf('/') > 0) { + let codeArray = comparisonOperand.code.split('/') comparisonOperand.algebra.operandA.code = codeArray[0] comparisonOperand.algebra.operandB.code = codeArray[1] - comparisonOperand.algebra.operator = ' / ' + comparisonOperand.algebra.operator = '/' comparisonOperand.algebra.operatorIndex = 4 } initializePickersSet(logicOperand, comparisonOperand, comparisonOperand.algebra.operandA) - initializePickersSet(logicOperand, comparisonOperand, comparisonOperand.algebra.operandA) - updatePickers(logicOperand, comparisonOperand, comparisonOperand.algebra.operandA) + initializePickersSet(logicOperand, comparisonOperand, comparisonOperand.algebra.operandB) updatePickers(logicOperand, comparisonOperand, comparisonOperand.algebra.operandA) + updatePickers(logicOperand, comparisonOperand, comparisonOperand.algebra.operandB) } function initializePickersSet (logicOperand, comparisonOperand, algebraOperand) { - /* Get the ySign */ - let ySign - if (algebraOperand.index === 0) { - ySign = -1 - } - if (algebraOperand.index === 1) { - ySign = 1 - } + const ALGEBRA_SEPARATION = PICKER_HEIGHT + const COMPARISON_SEPARATION = ALGEBRA_SEPARATION * 2 + const LOGIC_SEPARATION = COMPARISON_SEPARATION * 2 let properties let parent let current + let yOffset = (logicOperand.index - 1) * LOGIC_SEPARATION + (comparisonOperand.index - 0.5) * COMPARISON_SEPARATION + (algebraOperand.index - 0.5) * ALGEBRA_SEPARATION + + if (algebraOperand.index === 0) { + comparisonOperand.algebra.picker = newPicker() + let picker = comparisonOperand.algebra.picker + picker.name = 'Algebra' + picker.container.connectToParent(thisObject.container) + picker.container.frame.position.x = 0 - picker.container.frame.width / 2 + picker.container.frame.width * 2.5 + picker.container.frame.position.y = 0 - picker.container.frame.height / 2 + yOffset + current = ['...', 'Plus', 'Minus', 'Times', 'Divided by'] + picker.initialize(current, current) + switch (comparisonOperand.algebra.operator) { + case '+': { + picker.setSelected(undefined, undefined, undefined, 1) + break + } + case '-': { + picker.setSelected(undefined, undefined, undefined, 2) + break + } + case '*': { + picker.setSelected(undefined, undefined, undefined, 3) + break + } + case '/': { + picker.setSelected(undefined, undefined, undefined, 4) + break + } + } + picker.visible = true + let structureBranch = { + logicOperand: logicOperand, + comparisonOperand: comparisonOperand, + algebraOperand: algebraOperand, + pickerName: 'Algebra' + } + picker.eventSuscriptionId = picker.container.eventHandler.listenToEvent('onParentChanged', onParentChanged, structureBranch) + } + + if (comparisonOperand.index === 0 && algebraOperand.index === 1) { + logicOperand.comparison.picker = newPicker() + let picker = logicOperand.comparison.picker + picker.name = 'Comparison' + picker.container.connectToParent(thisObject.container) + picker.container.frame.position.x = 0 - picker.container.frame.width / 2 + picker.container.frame.width * 2.5 + picker.container.frame.position.y = 0 - picker.container.frame.height / 2 + yOffset + let optionsList = ['Greater Than', 'Less Than', 'Greater or Equal Than', 'Less or Equal Than', 'Equal To'] + picker.initialize(optionsList) + switch (logicOperand.comparison.operator) { + case '>': { + picker.setSelected(undefined, undefined, undefined, 0) + break + } + case '<': { + picker.setSelected(undefined, undefined, undefined, 1) + break + } + case '>=': { + picker.setSelected(undefined, undefined, undefined, 2) + break + } + case '<=': { + picker.setSelected(undefined, undefined, undefined, 3) + break + } + case '===': { + picker.setSelected(undefined, undefined, undefined, 4) + break + } + } + picker.visible = true + let structureBranch = { + logicOperand: logicOperand, + comparisonOperand: comparisonOperand, + algebraOperand: algebraOperand, + pickerName: 'Comparison' + } + picker.eventSuscriptionId = picker.container.eventHandler.listenToEvent('onParentChanged', onParentChanged, structureBranch) + } + + if (comparisonOperand.index === 1 && algebraOperand.index === 1 && logicOperand.index <= 1) { + logicOperand.picker = newPicker() + let picker = logicOperand.picker + picker.name = 'Logic' + picker.container.connectToParent(thisObject.container) + picker.container.frame.position.x = 0 - picker.container.frame.width / 2 + picker.container.frame.width * 2.5 + picker.container.frame.position.y = 0 - picker.container.frame.height / 2 + yOffset + let optionsList = ['...', 'OR'] + picker.initialize(optionsList) + if (logicOperand.operator === '||') { + picker.setSelected(undefined, undefined, undefined, 1) + } + picker.visible = true + let structureBranch = { + logicOperand: logicOperand, + comparisonOperand: comparisonOperand, + algebraOperand: algebraOperand, + pickerName: 'Logic' + } + picker.eventSuscriptionId = picker.container.eventHandler.listenToEvent('onParentChanged', onParentChanged, structureBranch) + } + + let visible = true + if (algebraOperand.index === 1 && comparisonOperand.algebra.picker.getSelected() === '...') { visible = false } + if (logicOperand.comparison.picker !== undefined && comparisonOperand.index === 1 && logicOperand.comparison.picker.getSelected() === 'Equal To') { visible = false } algebraOperand.whenPicker = newPicker() algebraOperand.whenPicker.name = 'When' algebraOperand.whenPicker.container.connectToParent(thisObject.container) - algebraOperand.whenPicker.container.frame.position.x = 0 - algebraOperand.whenPicker.container.frame.width / 2 - algebraOperand.whenPicker.container.frame.width * 1.0 - algebraOperand.whenPicker.container.frame.position.y = 0 - algebraOperand.whenPicker.container.frame.height / 2 + algebraOperand.whenPicker.container.frame.height * ySign + algebraOperand.whenPicker.container.frame.position.x = 0 - algebraOperand.whenPicker.container.frame.width / 2 - algebraOperand.whenPicker.container.frame.width * 0.5 + algebraOperand.whenPicker.container.frame.position.y = 0 - algebraOperand.whenPicker.container.frame.height / 2 + yOffset current = ['Current', '1 Previous', '2 Previous', '3 Previous', '4 Previous', '5 Previous'] algebraOperand.whenPicker.initialize(current, current) - algebraOperand.whenPicker.visible = true - - algebraOperand.algebraicPicker = newPicker() - algebraOperand.algebraicPicker.name = 'Algebraic' - algebraOperand.algebraicPicker.container.connectToParent(thisObject.container) - algebraOperand.algebraicPicker.container.frame.position.x = 0 - algebraOperand.algebraicPicker.container.frame.width / 2 + algebraOperand.algebraicPicker.container.frame.width * 3.0 - algebraOperand.algebraicPicker.container.frame.position.y = 0 - algebraOperand.algebraicPicker.container.frame.height / 2 + algebraOperand.algebraicPicker.container.frame.height * ySign - current = ['+ - * /', 'Plus', 'Minus', 'Times', 'Divided by'] - algebraOperand.algebraicPicker.initialize(current, current) - algebraOperand.algebraicPicker.visible = true + algebraOperand.whenPicker.visible = visible algebraOperand.dataMinePicker = newPicker() algebraOperand.dataMinePicker.name = 'Data Mine' algebraOperand.dataMinePicker.container.connectToParent(thisObject.container) - algebraOperand.dataMinePicker.container.frame.position.x = 0 - algebraOperand.dataMinePicker.container.frame.width / 2 - algebraOperand.dataMinePicker.container.frame.width * 3.0 - algebraOperand.dataMinePicker.container.frame.position.y = 0 - algebraOperand.dataMinePicker.container.frame.height / 2 + algebraOperand.dataMinePicker.container.frame.height * ySign + algebraOperand.dataMinePicker.container.frame.position.x = 0 - algebraOperand.dataMinePicker.container.frame.width / 2 - algebraOperand.dataMinePicker.container.frame.width * 2.5 + algebraOperand.dataMinePicker.container.frame.position.y = 0 - algebraOperand.dataMinePicker.container.frame.height / 2 + yOffset current = scanResult properties = Object.keys(current) algebraOperand.dataMinePicker.initialize(properties, current) parent = current - algebraOperand.dataMinePicker.visible = true + algebraOperand.dataMinePicker.visible = visible algebraOperand.botPicker = newPicker() algebraOperand.botPicker.name = 'Bot' algebraOperand.botPicker.container.connectToParent(thisObject.container) - algebraOperand.botPicker.container.frame.position.x = 0 - algebraOperand.botPicker.container.frame.width / 2 - algebraOperand.botPicker.container.frame.width * 2.0 - algebraOperand.botPicker.container.frame.position.y = 0 - algebraOperand.botPicker.container.frame.height / 2 + algebraOperand.dataMinePicker.container.frame.height * ySign + algebraOperand.botPicker.container.frame.position.x = 0 - algebraOperand.botPicker.container.frame.width / 2 - algebraOperand.botPicker.container.frame.width * 1.5 + algebraOperand.botPicker.container.frame.position.y = 0 - algebraOperand.botPicker.container.frame.height / 2 + yOffset current = parent[properties[0]] properties = Object.keys(current) algebraOperand.botPicker.initialize(properties, current, parent) parent = current - algebraOperand.botPicker.visible = true + algebraOperand.botPicker.visible = visible algebraOperand.productPicker = newPicker() algebraOperand.productPicker.name = 'Product' algebraOperand.productPicker.container.connectToParent(thisObject.container) - algebraOperand.productPicker.container.frame.position.x = 0 - algebraOperand.productPicker.container.frame.width / 2 + algebraOperand.productPicker.container.frame.width * 0.0 - algebraOperand.productPicker.container.frame.position.y = 0 - algebraOperand.productPicker.container.frame.height / 2 + algebraOperand.dataMinePicker.container.frame.height * ySign + algebraOperand.productPicker.container.frame.position.x = 0 - algebraOperand.productPicker.container.frame.width / 2 + algebraOperand.productPicker.container.frame.width * 0.5 + algebraOperand.productPicker.container.frame.position.y = 0 - algebraOperand.productPicker.container.frame.height / 2 + yOffset current = parent[properties[0]] properties = Object.keys(current) algebraOperand.productPicker.initialize(properties, current, parent) parent = current - algebraOperand.productPicker.visible = true + algebraOperand.productPicker.visible = visible let productParent = parent let productProperties = properties @@ -271,36 +399,40 @@ function newConditionEditor () { algebraOperand.propertyPicker = newPicker() algebraOperand.propertyPicker.name = 'Property' algebraOperand.propertyPicker.container.connectToParent(thisObject.container) - algebraOperand.propertyPicker.container.frame.position.x = 0 - algebraOperand.propertyPicker.container.frame.width / 2 + algebraOperand.propertyPicker.container.frame.width * 1.0 - algebraOperand.propertyPicker.container.frame.position.y = 0 - algebraOperand.propertyPicker.container.frame.height / 2 + algebraOperand.dataMinePicker.container.frame.height * ySign + algebraOperand.propertyPicker.container.frame.position.x = 0 - algebraOperand.propertyPicker.container.frame.width / 2 + algebraOperand.propertyPicker.container.frame.width * 1.5 + algebraOperand.propertyPicker.container.frame.position.y = 0 - algebraOperand.propertyPicker.container.frame.height / 2 + yOffset current = productParent[productProperties[0]] current = current.properties properties = Object.keys(current) algebraOperand.propertyPicker.initialize(properties, current, productParent, 'properties') parent = current - algebraOperand.propertyPicker.visible = true + algebraOperand.propertyPicker.visible = visible algebraOperand.valuePicker = newPicker() algebraOperand.valuePicker.name = 'Value' algebraOperand.valuePicker.container.connectToParent(thisObject.container) - algebraOperand.valuePicker.container.frame.position.x = 0 - algebraOperand.valuePicker.container.frame.width / 2 - algebraOperand.valuePicker.container.frame.position.y = 0 - algebraOperand.valuePicker.container.frame.height / 2 + algebraOperand.valuePicker.container.frame.height * 1 + algebraOperand.valuePicker.container.frame.position.x = 0 - algebraOperand.valuePicker.container.frame.width / 2 + algebraOperand.valuePicker.container.frame.width * 3.5 + algebraOperand.valuePicker.container.frame.position.y = 0 - algebraOperand.valuePicker.container.frame.height / 2 + yOffset + ALGEBRA_SEPARATION current = parent[properties[0]] properties = current.possibleValues algebraOperand.valuePicker.initialize(properties, current, parent, 'possibleValues') parent = current algebraOperand.valuePicker.visible = false + if (logicOperand.comparison.picker !== undefined && logicOperand.comparison.picker.getSelected() === 'Equal To') { + comparisonOperand.algebra.operandA.valuePicker.visible = true + } algebraOperand.timeFramePicker = newPicker() algebraOperand.timeFramePicker.name = 'Time Frame' algebraOperand.timeFramePicker.container.connectToParent(thisObject.container) - algebraOperand.timeFramePicker.container.frame.position.x = 0 - algebraOperand.timeFramePicker.container.frame.width / 2 + algebraOperand.timeFramePicker.container.frame.width * 2.0 - algebraOperand.timeFramePicker.container.frame.position.y = 0 - algebraOperand.timeFramePicker.container.frame.height / 2 + algebraOperand.timeFramePicker.container.frame.height * ySign + algebraOperand.timeFramePicker.container.frame.position.x = 0 - algebraOperand.timeFramePicker.container.frame.width / 2 - algebraOperand.timeFramePicker.container.frame.width * 3.0 + algebraOperand.timeFramePicker.container.frame.position.y = 0 - algebraOperand.timeFramePicker.container.frame.height / 2 + yOffset + algebraOperand.timeFramePicker.container.frame.width = algebraOperand.timeFramePicker.container.frame.width / 2 current = productParent[productProperties[0]] properties = current.validTimeFrames algebraOperand.timeFramePicker.initialize(properties, current, productParent, 'validTimeFrames') parent = current - algebraOperand.timeFramePicker.visible = true + algebraOperand.timeFramePicker.visible = visible algebraOperand.botPicker.eventSuscriptionId = algebraOperand.dataMinePicker.container.eventHandler.listenToEvent('onParentChanged', algebraOperand.botPicker.onParentChanged) algebraOperand.productPicker.eventSuscriptionId = algebraOperand.botPicker.container.eventHandler.listenToEvent('onParentChanged', algebraOperand.productPicker.onParentChanged) @@ -312,8 +444,15 @@ function newConditionEditor () { function updatePickers (logicOperand, comparisonOperand, algebraOperand) { let codeArray = algebraOperand.code.split('.') - let codeTimeFrame = codeArray[1].substring(2, 4) + '-' + codeArray[1].substring(4, 7) - let codeProduct = codeArray[2] + let codeTimeFrame + if (codeArray[1] !== undefined) { + codeTimeFrame = codeArray[1].substring(2, 4) + '-' + codeArray[1].substring(4, 7) + } + + let codeProduct + if (codeArray[2] !== undefined) { + codeProduct = codeArray[2] + } /* Parse When */ let propertyDisplacement = 0 @@ -340,8 +479,12 @@ function newConditionEditor () { } algebraOperand.whenPicker.setSelected(undefined, undefined, undefined, propertyDisplacement) - let codeProperty = codeArray[3 + propertyDisplacement] - let codeValue = comparisonOperand.algebra.operandB.code.replace('"', '').replace('"', '') + let codeProperty + if (codeArray[3 + propertyDisplacement] !== undefined) { + codeProperty = codeArray[3 + propertyDisplacement] + } + + let codeValue = logicOperand.comparison.operandB.code.replace('"', '').replace('"', '') let dataMines = Object.keys(scanResult) for (let i = 0; i < dataMines.length; i++) { @@ -457,89 +600,157 @@ function newConditionEditor () { } function convertToCode () { - // if (comparisonOperatorA === undefined || comparisonOperatorB === undefined || comparisonPicker === undefined) { return } + if (conditionStructure === undefined) { return } // chart.at01hs.bollingerSubChannel.previous.previous.slope=== "Extreme" - /* + let code = '' - code = code + 'chart.at' + comparisonOperatorA.timeFramePicker.getSelected().replace('-', '') - code = code + '.' + comparisonOperatorA.productPicker.getSelected() - insertWhen(comparisonOperatorA) - code = code + '.' + comparisonOperatorA.propertyPicker.getSelected() - - switch (comparisonPicker.getSelected()) { - case 'Greater Than': { - code = code + ' > ' + for (let i = 0; i < conditionStructure.logicOperands.length; i++) { + let logicOperand = conditionStructure.logicOperands[i] + logicOperandToCode(logicOperand) + if (logicOperand.picker.getSelected() !== 'OR') { break + } else { + code = code + ' || ' } - case 'Less Than': { - code = code + ' < ' - break - } - case 'Greater or Equal Than': { - code = code + ' >= ' - break - } - case 'Less or Equal Than': { - code = code + ' <= ' - break - } - case 'Equal To': { - code = code + ' === ' - break - } - } - - if (comparisonPicker.getSelected() === 'Equal To') { - code = code + '"' + comparisonOperatorA.valuePicker.getSelected() + '"' - } else { - code = code + 'chart.at' + comparisonOperatorB.timeFramePicker.getSelected().replace('-', '') - code = code + '.' + comparisonOperatorB.productPicker.getSelected() - insertWhen(comparisonOperatorB) - code = code + '.' + comparisonOperatorB.propertyPicker.getSelected() } thisObject.payload.node.code = code - function insertWhen (operator) { - switch (operator.whenPicker.getSelected()) { - case 'Current': { - return + function logicOperandToCode (logicOperand) { + algebraOperandToCode(logicOperand.comparison.operandA.algebra.operandA) + if (logicOperand.comparison.operandA.algebra.picker.getSelected() !== '...') { + insertAlgebraOperator(logicOperand.comparison.operandA.algebra) + algebraOperandToCode(logicOperand.comparison.operandA.algebra.operandB) + } + + switch (logicOperand.comparison.picker.getSelected()) { + case 'Greater Than': { + code = code + ' > ' + break } - case '1 Previous': { - code = code + '.previous' - return + case 'Less Than': { + code = code + ' < ' + break } - case '2 Previous': { - code = code + '.previous.previous' - return + case 'Greater or Equal Than': { + code = code + ' >= ' + break } - case '3 Previous': { - code = code + '.previous.previous.previous' - return + case 'Less or Equal Than': { + code = code + ' <= ' + break } - case '4 Previous': { - code = code + '.previous.previous.previous.previous' - return + case 'Equal To': { + code = code + ' === ' + break } - case '5 Previous': { - code = code + '.previous.previous.previous.previous.previous' - return + } + + if (logicOperand.comparison.picker.getSelected() === 'Equal To') { + code = code + '"' + logicOperand.comparison.operandA.algebra.operandA.valuePicker.getSelected() + '"' + } else { + algebraOperandToCode(logicOperand.comparison.operandB.algebra.operandA) + if (logicOperand.comparison.operandB.algebra.picker.getSelected() !== '...') { + insertAlgebraOperator(logicOperand.comparison.operandB.algebra) + algebraOperandToCode(logicOperand.comparison.operandB.algebra.operandB) + } + } + + function algebraOperandToCode (algebraOperand) { + if (algebraOperand.timeFramePicker.getSelected() === 'Any Time Frame') { + code = code + 'chart.atAnyTimeFrame' + } else { + code = code + 'chart.at' + algebraOperand.timeFramePicker.getSelected().replace('-', '') + } + + code = code + '.' + algebraOperand.productPicker.getSelected() + insertWhen(algebraOperand) + code = code + '.' + algebraOperand.propertyPicker.getSelected() + } + + function insertAlgebraOperator (algebra) { + switch (algebra.picker.getSelected()) { + case '...': { + return + } + case 'Plus': { + code = code + ' + ' + return + } + case 'Minus': { + code = code + ' - ' + return + } + case 'Times': { + code = code + ' * ' + return + } + case 'Divided by': { + code = code + ' / ' + return + } + } + } + function insertWhen (algebraOperand) { + switch (algebraOperand.whenPicker.getSelected()) { + case 'Current': { + return + } + case '1 Previous': { + code = code + '.previous' + return + } + case '2 Previous': { + code = code + '.previous.previous' + return + } + case '3 Previous': { + code = code + '.previous.previous.previous' + return + } + case '4 Previous': { + code = code + '.previous.previous.previous.previous' + return + } + case '5 Previous': { + code = code + '.previous.previous.previous.previous.previous' + return + } } } } - */ } function finalizePickers () { if (conditionStructure === undefined) { return } - for (let i = 0; i < conditionStructure.orOperands.length; i++) { - let logicOperand = conditionStructure.orOperands[i] + for (let i = 0; i < conditionStructure.logicOperands.length; i++) { + let logicOperand = conditionStructure.logicOperands[i] finalizeOperator(logicOperand.comparison.operandA.algebra.operandA) finalizeOperator(logicOperand.comparison.operandA.algebra.operandB) finalizeOperator(logicOperand.comparison.operandB.algebra.operandA) finalizeOperator(logicOperand.comparison.operandB.algebra.operandB) + + if (logicOperand.comparison.operandA.algebra.picker !== undefined) { + logicOperand.comparison.operandA.algebra.picker.container.eventHandler.stopListening(logicOperand.comparison.operandA.algebra.picker.eventSuscriptionId) + logicOperand.comparison.operandA.algebra.picker.finalize() + } + + if (logicOperand.comparison.operandB.algebra.picker !== undefined) { + logicOperand.comparison.operandB.algebra.picker.container.eventHandler.stopListening(logicOperand.comparison.operandB.algebra.picker.eventSuscriptionId) + logicOperand.comparison.operandB.algebra.picker.finalize() + } + + if (logicOperand.comparison.picker !== undefined) { + logicOperand.comparison.picker.container.eventHandler.stopListening(logicOperand.comparison.picker.eventSuscriptionId) + logicOperand.comparison.picker.finalize() + } + + if (logicOperand.picker !== undefined) { + logicOperand.picker.container.eventHandler.stopListening(logicOperand.picker.eventSuscriptionId) + logicOperand.picker.finalize() + } } } @@ -551,11 +762,6 @@ function newConditionEditor () { operand.whenPicker = undefined } - if (operand.algebraicPicker !== undefined) { - operand.algebraicPicker.finalize() - operand.algebraicPicker = undefined - } - if (operand.dataMinePicker !== undefined) { operand.dataMinePicker.container.eventHandler.stopListening(operand.botPicker.eventSuscriptionId) operand.dataMinePicker.finalize() @@ -592,27 +798,79 @@ function newConditionEditor () { } } - function onParentChanged (event) { - if (event.selected === 4) { - // this means Equal To + function onParentChanged (event, structureBranch) { + let logicOperand = structureBranch.logicOperand - comparisonOperatorA.valuePicker.visible = true - comparisonOperatorB.whenPicker.visible = false - comparisonOperatorB.algebraicPicker.visible = false - comparisonOperatorB.dataMinePicker.visible = false - comparisonOperatorB.botPicker.visible = false - comparisonOperatorB.productPicker.visible = false - comparisonOperatorB.propertyPicker.visible = false - comparisonOperatorB.timeFramePicker.visible = false - } else { - comparisonOperatorA.valuePicker.visible = false - comparisonOperatorB.whenPicker.visible = true - comparisonOperatorB.algebraicPicker.visible = true - comparisonOperatorB.dataMinePicker.visible = true - comparisonOperatorB.botPicker.visible = true - comparisonOperatorB.productPicker.visible = true - comparisonOperatorB.propertyPicker.visible = true - comparisonOperatorB.timeFramePicker.visible = true + if (structureBranch.pickerName === 'Logic') { + if (event.selected === 0) { + if (logicOperand.index === 0) { + conditionStructure.logicOperands[1].visible = false + conditionStructure.logicOperands[2].visible = false + } + if (logicOperand.index === 1) { + conditionStructure.logicOperands[2].visible = false + } + } else { + if (logicOperand.index === 0) { + conditionStructure.logicOperands[1].visible = true + + if (conditionStructure.logicOperands[1].picker.getSelected() !== '...') { + conditionStructure.logicOperands[2].visible = true + } + } + if (logicOperand.index === 1) { + conditionStructure.logicOperands[2].visible = true + } + } + } + + if (structureBranch.pickerName === 'Algebra') { + if (event.selected === 0) { + setVisibility(structureBranch.comparisonOperand.algebra.operandB, false) + } else { + setVisibility(structureBranch.comparisonOperand.algebra.operandB, true) + } + } + + if (structureBranch.pickerName === 'Comparison') { + if (event.selected === 4) { + // this means Equal To + + logicOperand.comparison.operandA.algebra.operandA.valuePicker.visible = true + logicOperand.comparison.operandA.algebra.picker.visible = false + logicOperand.comparison.operandB.algebra.picker.visible = false + setVisibility(logicOperand.comparison.operandA.algebra.operandB, false) + setVisibility(logicOperand.comparison.operandB.algebra.operandA, false) + setVisibility(logicOperand.comparison.operandB.algebra.operandB, false) + } else { + logicOperand.comparison.operandA.algebra.operandA.valuePicker.visible = false + logicOperand.comparison.operandA.algebra.picker.visible = true + logicOperand.comparison.operandB.algebra.picker.visible = true + if (logicOperand.comparison.operandA.algebra.picker.getSelected() !== '...') { + setVisibility(logicOperand.comparison.operandA.algebra.operandB, true) + } + + if (logicOperand.comparison.picker.getSelected() !== 'Equal To') { + setVisibility(logicOperand.comparison.operandB.algebra.operandA, true) + } + + if (logicOperand.comparison.operandB.algebra.picker.getSelected() !== '...') { + setVisibility(logicOperand.comparison.operandB.algebra.operandB, true) + } + } + } + + function setLogicOperanVisibility (logicOperand, isVisible) { + + } + + function setVisibility (algebraOperand, isVisible) { + algebraOperand.whenPicker.visible = isVisible + algebraOperand.dataMinePicker.visible = isVisible + algebraOperand.botPicker.visible = isVisible + algebraOperand.productPicker.visible = isVisible + algebraOperand.propertyPicker.visible = isVisible + algebraOperand.timeFramePicker.visible = isVisible } } @@ -621,8 +879,10 @@ function newConditionEditor () { if (thisObject.visible === true) { if (conditionStructure === undefined) { return } - for (let i = 0; i < conditionStructure.orOperands.length; i++) { - let logicOperand = conditionStructure.orOperands[i] + for (let i = 0; i < conditionStructure.logicOperands.length; i++) { + let logicOperand = conditionStructure.logicOperands[i] + if (logicOperand.visible !== true) { continue } + container = operandGetContainer(point, logicOperand.comparison.operandA.algebra.operandA) if (container !== undefined) { return container } container = operandGetContainer(point, logicOperand.comparison.operandA.algebra.operandB) @@ -631,6 +891,34 @@ function newConditionEditor () { if (container !== undefined) { return container } container = operandGetContainer(point, logicOperand.comparison.operandB.algebra.operandB) if (container !== undefined) { return container } + + if (container = logicOperand.comparison.operandA.algebra.picker !== undefined) { + if (container = logicOperand.comparison.operandA.algebra.picker.visible === true) { + container = logicOperand.comparison.operandA.algebra.picker.getContainer(point) + if (container !== undefined) { return container } + } + } + + if (logicOperand.comparison.operandB.algebra.picker !== undefined) { + if (container = logicOperand.comparison.operandB.algebra.picker.visible === true) { + container = logicOperand.comparison.operandB.algebra.picker.getContainer(point) + if (container !== undefined) { return container } + } + } + + if (container = logicOperand.comparison.picker !== undefined) { + if (container = logicOperand.comparison.picker.visible === true) { + container = logicOperand.comparison.picker.getContainer(point) + if (container !== undefined) { return container } + } + } + + if (container = logicOperand.picker !== undefined) { + if (container = logicOperand.picker.visible === true) { + container = logicOperand.picker.getContainer(point) + if (container !== undefined) { return container } + } + } } if (thisObject.container.frame.isThisPointHere(point, true) === true) { @@ -650,13 +938,6 @@ function newConditionEditor () { } } - if (operand.algebraicPicker !== undefined) { - if (operand.algebraicPicker.visible === true) { - container = operand.algebraicPicker.getContainer(point) - if (container !== undefined) { return container } - } - } - if (operand.dataMinePicker !== undefined) { if (operand.dataMinePicker.visible === true) { container = operand.dataMinePicker.getContainer(point) @@ -712,12 +993,35 @@ function newConditionEditor () { function childrenDrawBackground () { if (conditionStructure === undefined) { return } - for (let i = 0; i < conditionStructure.orOperands.length; i++) { - let logicOperand = conditionStructure.orOperands[i] + for (let i = 0; i < conditionStructure.logicOperands.length; i++) { + let logicOperand = conditionStructure.logicOperands[i] + if (logicOperand.visible !== true) { continue } + operandDrawBackground(logicOperand.comparison.operandA.algebra.operandA) operandDrawBackground(logicOperand.comparison.operandA.algebra.operandB) operandDrawBackground(logicOperand.comparison.operandB.algebra.operandA) operandDrawBackground(logicOperand.comparison.operandB.algebra.operandB) + + if (logicOperand.comparison.operandA.algebra.picker !== undefined) { + if (logicOperand.comparison.operandA.algebra.picker.visible === true) { + logicOperand.comparison.operandA.algebra.picker.drawBackground() + } + } + if (logicOperand.comparison.operandB.algebra.picker !== undefined) { + if (logicOperand.comparison.operandB.algebra.picker.visible === true) { + logicOperand.comparison.operandB.algebra.picker.drawBackground() + } + } + if (logicOperand.comparison.picker !== undefined) { + if (logicOperand.comparison.picker.visible === true) { + logicOperand.comparison.picker.drawBackground() + } + } + if (logicOperand.picker !== undefined) { + if (logicOperand.picker.visible === true) { + logicOperand.picker.drawBackground() + } + } } } @@ -730,12 +1034,6 @@ function newConditionEditor () { } } - if (operand.algebraicPicker !== undefined) { - if (operand.algebraicPicker.visible === true) { - operand.algebraicPicker.drawBackground() - } - } - if (operand.dataMinePicker !== undefined) { if (operand.dataMinePicker.visible === true) { operand.dataMinePicker.drawBackground() @@ -806,12 +1104,35 @@ function newConditionEditor () { function childrenDrawForeground () { if (conditionStructure === undefined) { return } - for (let i = 0; i < conditionStructure.orOperands.length; i++) { - let logicOperand = conditionStructure.orOperands[i] + for (let i = 0; i < conditionStructure.logicOperands.length; i++) { + let logicOperand = conditionStructure.logicOperands[i] + if (logicOperand.visible !== true) { continue } + operandDrawForeground(logicOperand.comparison.operandA.algebra.operandA) operandDrawForeground(logicOperand.comparison.operandA.algebra.operandB) operandDrawForeground(logicOperand.comparison.operandB.algebra.operandA) operandDrawForeground(logicOperand.comparison.operandB.algebra.operandB) + + if (logicOperand.comparison.operandA.algebra.picker !== undefined) { + if (logicOperand.comparison.operandA.algebra.picker.visible === true) { + logicOperand.comparison.operandA.algebra.picker.drawForeground() + } + } + if (logicOperand.comparison.operandB.algebra.picker !== undefined) { + if (logicOperand.comparison.operandB.algebra.picker.visible === true) { + logicOperand.comparison.operandB.algebra.picker.drawForeground() + } + } + if (logicOperand.comparison.picker !== undefined) { + if (logicOperand.comparison.picker.visible === true) { + logicOperand.comparison.picker.drawForeground() + } + } + if (logicOperand.picker !== undefined) { + if (logicOperand.picker.visible === true) { + logicOperand.picker.drawForeground() + } + } } } @@ -824,12 +1145,6 @@ function newConditionEditor () { } } - if (operand.algebraicPicker !== undefined) { - if (operand.algebraicPicker.visible === true) { - operand.algebraicPicker.drawForeground() - } - } - if (operand.dataMinePicker !== undefined) { if (operand.dataMinePicker.visible === true) { operand.dataMinePicker.drawForeground() @@ -868,6 +1183,16 @@ function newConditionEditor () { } function thisObjectDrawForeground () { - + if (thisObject.visible === true) { + const SIZE = 36 + drawIcon(timeFrameIcon, 0, 0, -PICKER_WIDTH * 3.25, -PICKER_HEIGHT * 7, SIZE, thisObject.container) + drawIcon(dataMineIcon, 0, 0, -PICKER_WIDTH * 2.5, -PICKER_HEIGHT * 7, SIZE, thisObject.container) + drawIcon(botIcon, 0, 0, -PICKER_WIDTH * 1.5, -PICKER_HEIGHT * 7, SIZE, thisObject.container) + drawIcon(whenIcon, 0, 0, -PICKER_WIDTH * 0.5, -PICKER_HEIGHT * 7, SIZE, thisObject.container) + drawIcon(productIcon, 0, 0, PICKER_WIDTH * 0.5, -PICKER_HEIGHT * 7, SIZE, thisObject.container) + drawIcon(propertyIcon, 0, 0, PICKER_WIDTH * 1.45, -PICKER_HEIGHT * 7, SIZE, thisObject.container) + drawIcon(operationIcon, 0, 0, PICKER_WIDTH * 2.45, -PICKER_HEIGHT * 7, SIZE, thisObject.container) + drawIcon(valueIcon, 0, 0, PICKER_WIDTH * 3.45, -PICKER_HEIGHT * 7, SIZE, thisObject.container) + } } } diff --git a/FloatingSpace/ConfigEditor.js b/FloatingSpace/ConfigEditor.js index b25331644..8cb2ffb83 100644 --- a/FloatingSpace/ConfigEditor.js +++ b/FloatingSpace/ConfigEditor.js @@ -52,10 +52,10 @@ function newConfigEditor () { thisObject.visible = false let textArea = document.getElementById('textArea') textArea.style.display = 'none' - thisObject.payload.node.code = textArea.value + thisObject.payload.node.config = textArea.value try { - let code = JSON.parse(thisObject.payload.node.code) + let config = JSON.parse(thisObject.payload.node.config) } catch (err) { thisObject.payload.uiObject.setErrorMessage(err.message, 10) } @@ -72,7 +72,7 @@ function newConfigEditor () { thisObject.payload.uiObject.setErrorMessage('', 0) let textArea = document.getElementById('textArea') - textArea.value = payload.node.code + textArea.value = payload.node.config textArea.style = 'resize: none;' + ' border: none;' + ' outline: none;' + @@ -94,7 +94,7 @@ function newConfigEditor () { if (thisObject.visible === true) { if (point.x === VERY_LARGE_NUMBER) { /* The the mouse leaves the canvas, and event of mouse over with a ridiculous coordinate is triggered so that - anyone can react. In our case, the code editor has a text area that is not part of the canvas, so the event is + anyone can react. In our case, the config editor has a text area that is not part of the canvas, so the event is triggered. We compensate recognizing this coordinate and returning our container. */ return thisObject.container } diff --git a/FloatingSpace/Picker.js b/FloatingSpace/Picker.js index 885b01c11..b306ac85e 100644 --- a/FloatingSpace/Picker.js +++ b/FloatingSpace/Picker.js @@ -25,8 +25,8 @@ function newPicker () { thisObject.container.frame.radius = 0 thisObject.container.frame.position.x = 0 thisObject.container.frame.position.y = 0 - thisObject.container.frame.width = 200 - thisObject.container.frame.height = 120 + thisObject.container.frame.width = 150 + thisObject.container.frame.height = 60 let isMouseOver let optionsList @@ -175,7 +175,7 @@ function newPicker () { } function drawForeground () { - const FONT_SIZE = 20 + const FONT_SIZE = 15 const VISIBLE_LABELS = 5 let fontSize let fontColor @@ -190,11 +190,11 @@ function newPicker () { fontColor = UI_COLOR.LIGHT_GREY switch (i) { case 0: - fontSize = FONT_SIZE - 10 + fontSize = FONT_SIZE - 5 opacity = 0.4 break case 1: - fontSize = FONT_SIZE - 5 + fontSize = FONT_SIZE - 3 opacity = 0.5 break case 2: @@ -203,11 +203,11 @@ function newPicker () { opacity = 1 break case 3: - fontSize = FONT_SIZE - 5 + fontSize = FONT_SIZE - 3 opacity = 0.5 break case 4: - fontSize = FONT_SIZE - 10 + fontSize = FONT_SIZE - 5 opacity = 0.4 break } diff --git a/FloatingSpace/UiObject.js b/FloatingSpace/UiObject.js index 8cc05dbf8..00740dcd9 100644 --- a/FloatingSpace/UiObject.js +++ b/FloatingSpace/UiObject.js @@ -363,7 +363,7 @@ function newUiObject () { } function childrenRunningPhysics () { - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition.properties === undefined) { return } let monitorChildrenRunning = false for (let i = 0; i < nodeDefinition.properties.length; i++) { @@ -407,7 +407,7 @@ function newUiObject () { let nearbyFloatingObjects = thisObject.payload.floatingObject.nearbyFloatingObjects let compatibleTypes - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition !== undefined) { if (nodeDefinition.chainAttachesTo !== undefined) { compatibleTypes = nodeDefinition.chainAttachesTo.compatibleTypes @@ -429,10 +429,10 @@ function newUiObject () { let nearbyNode = floatingObject.payload.node if (compatibleTypes.indexOf('->' + nearbyNode.type + '->') >= 0) { /* Discard App Schema defined objects with busy coonection ports */ - nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition !== undefined) { let mustContinue = false - let parentNodeDefinition = APP_SCHEMA_MAP.get(nearbyNode.type) + let parentNodeDefinition = getNodeDefinition(nearbyNode) if (parentNodeDefinition !== undefined) { if (parentNodeDefinition.properties !== undefined) { for (let j = 0; j < parentNodeDefinition.properties.length; j++) { @@ -560,7 +560,7 @@ function newUiObject () { let nearbyFloatingObjects = thisObject.payload.floatingObject.nearbyFloatingObjects let compatibleTypes - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition !== undefined) { if (nodeDefinition.referenceAttachesTo !== undefined) { compatibleTypes = nodeDefinition.referenceAttachesTo.compatibleTypes @@ -842,7 +842,7 @@ function newUiObject () { function iconPhysics () { icon = canvas.designSpace.iconByUiObjectType.get(thisObject.payload.node.type) - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition.alternativeIcons !== undefined) { let nodeToUse = thisObject.payload.node if (nodeDefinition.alternativeIcons === 'Use Reference Parent') { @@ -859,15 +859,15 @@ function newUiObject () { } } } - nodeDefinition = APP_SCHEMA_MAP.get(nodeToUse.type) - let code = nodeToUse.code + nodeDefinition = getNodeDefinition(nodeToUse) + let config = nodeToUse.config try { - code = JSON.parse(code) + config = JSON.parse(config) let alternativeIcon let iconName for (let i = 0; i < nodeDefinition.alternativeIcons.length; i++) { alternativeIcon = nodeDefinition.alternativeIcons[i] - if (alternativeIcon.codeName === code.codeName) { + if (alternativeIcon.codeName === config.codeName) { iconName = alternativeIcon.iconName } } @@ -1205,7 +1205,26 @@ function newUiObject () { } } + 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 drawText () { + if (isEditorVisible() === true) { return } /* Text Follows */ let position = { x: 0, @@ -1242,7 +1261,7 @@ function newUiObject () { if (canvas.floatingSpace.inMapMode === true) { labelPoint.y = labelPoint.y - 20 - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition !== undefined) { if (nodeDefinition.isHierarchyHead !== true) { return @@ -1332,7 +1351,7 @@ function newUiObject () { label = currentValue if (!isNaN(label)) { if (currentValue.toFixed !== undefined) { - label = currentValue.toFixed(2) + label = dynamicDecimals(currentValue, 2) } } @@ -1559,7 +1578,7 @@ function newUiObject () { browserCanvasContext.fill() - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition !== undefined) { if (nodeDefinition.isHierarchyHead === true) { VISIBLE_RADIUS = thisObject.payload.floatingObject.currentHierarchyRing * 2.8 @@ -1741,7 +1760,7 @@ function newUiObject () { let totalImageSize = additionalImageSize + thisObject.payload.floatingObject.currentImageSize if (canvas.floatingSpace.inMapMode === true) { totalImageSize = canvas.floatingSpace.transformImagesizeToMap(totalImageSize) - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition(thisObject.payload.node) if (nodeDefinition !== undefined) { if (nodeDefinition.isHierarchyHead !== true) { totalImageSize = totalImageSize / 4 diff --git a/FloatingSpace/UiObjectConstructor.js b/FloatingSpace/UiObjectConstructor.js index 0be9a5a24..b2445657a 100644 --- a/FloatingSpace/UiObjectConstructor.js +++ b/FloatingSpace/UiObjectConstructor.js @@ -74,7 +74,7 @@ function newUiObjectConstructor () { */ if (userAddingNew === true) { - let definition = APP_SCHEMA_MAP.get(payload.parentNode.type) + let definition = getNodeDefinition (payload.parentNode) if (definition.properties !== undefined) { for (let i = 0; i < definition.properties.length; i++) { let property = definition.properties[i] @@ -406,7 +406,7 @@ function newUiObjectConstructor () { function getMenuItemsInitialValues (uiObject, floatingObject, payload) { let menuItemsInitialValues = [] - let nodeDefinition = APP_SCHEMA_MAP.get(payload.node.type) + let nodeDefinition = getNodeDefinition (payload.node) if (nodeDefinition !== undefined) { if (nodeDefinition.editors !== undefined) { if (nodeDefinition.editors.config === true) { @@ -495,7 +495,7 @@ function newUiObjectConstructor () { } default: { - let nodeDefinition = APP_SCHEMA_MAP.get(payload.node.type) + let nodeDefinition = getNodeDefinition (payload.node) if (nodeDefinition !== undefined) { switch (nodeDefinition.level) { case 0: { diff --git a/FloatingSpace/UiObjectTitle.js b/FloatingSpace/UiObjectTitle.js index e96b23eac..89e39c5c0 100644 --- a/FloatingSpace/UiObjectTitle.js +++ b/FloatingSpace/UiObjectTitle.js @@ -51,7 +51,7 @@ function newUiObjectTitle () { thisObject.payload = payload thisObject.allwaysVisible = false // Default value - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition (thisObject.payload.node) if (nodeDefinition !== undefined) { if (nodeDefinition.isTitleAllwaysVisible === true) { thisObject.allwaysVisible = true @@ -100,7 +100,7 @@ function newUiObjectTitle () { if (thisObject.payload.title === undefined) { return } /* It is possible to override the default title by setting the APP SCHEMA property 'title' */ - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition (thisObject.payload.node) if (nodeDefinition.title !== undefined) { thisObject.payload.title = '' thisObject.payload.node.name = '' @@ -221,7 +221,7 @@ function newUiObjectTitle () { } function onMouseClick (event) { - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition (thisObject.payload.node) if (nodeDefinition.title !== undefined) { return } let checkPoint = { @@ -329,7 +329,7 @@ function newUiObjectTitle () { labelPoint.x = labelPoint.x - label.length / 2 * fontSize * FONT_ASPECT_RATIO labelPoint.y = labelPoint.y - 35 - let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type) + let nodeDefinition = getNodeDefinition (thisObject.payload.node) if (nodeDefinition !== undefined) { if (nodeDefinition.isHierarchyHead !== true) { return diff --git a/Globals.js b/Globals.js index cc1ec296a..d9a737c01 100644 --- a/Globals.js +++ b/Globals.js @@ -190,8 +190,7 @@ const MAX_PLOTABLE_DATE = maxDate; const TOP_SPACE_HEIGHT = 40 const COCKPIT_SPACE_HEIGHT = 30; -const BREAKPOINT_HEIGHT = 15; -const SIDE_PANEL_WIDTH = 450 +const SIDE_PANEL_WIDTH = 350 let COCKPIT_SPACE_POSITION = browserCanvas.height - COCKPIT_SPACE_HEIGHT const LAYER_STATUS = { @@ -222,7 +221,13 @@ const TIME_MACHINE_WIDTH = 8; const TIME_MACHINE_HEIGHT = 8; let mediaRecorder // to downloadText canvas animation as a mediaRecorder -let areWeRecording = false +let marketPanoramaCanvas +let ARE_WE_RECORDING_A_VIDEO = false +let ARE_WE_RECORDING_A_MARKET_PANORAMA = false +let PANORAMA_WAS_PANNED = false +let CURRENT_PANORAMA_POSITION = 0 + +let canWeDraw = false // This global variable regulates when spaces can or can not draw their contents. function toRadians(angle) { return angle * (Math.PI / 180); diff --git a/Panels/Layer.js b/Panels/Layer.js index 44e067063..c1ac56823 100644 --- a/Panels/Layer.js +++ b/Panels/Layer.js @@ -170,7 +170,7 @@ function newLayer () { 'Plotter Module->Plotter->' + 'Shapes->' + 'Chart Points->Point->Point Formula->' + - 'Polygon->Polygon Body->Style->Style Condition->Style->' + + 'Polygon->Polygon Condition->Polygon Body->Style->Style Condition->Style->' + 'Polygon Border->Style->Style Condition->Style->' + 'Polygon Vertex->Point->' + 'Plotter Panel->Javascript Code->Panel Data->Data Formula->' @@ -200,7 +200,7 @@ function newLayer () { /* Get ready to draw this layer */ thisObject.baseAsset = thisObject.definition.referenceParent.parentNode.referenceParent.baseAsset.referenceParent thisObject.quotedAsset = thisObject.definition.referenceParent.parentNode.referenceParent.quotedAsset.referenceParent - thisObject.market = thisObject.baseAsset.code.codeName + '/' + thisObject.quotedAsset.code.codeName + thisObject.market = thisObject.baseAsset.config.codeName + '/' + thisObject.quotedAsset.config.codeName thisObject.exchange = thisObject.definition.referenceParent.parentNode.referenceParent.parentNode.parentNode /* Some basic validations. */ @@ -226,8 +226,8 @@ function newLayer () { thisObject.exchangeIcon = getIcon(thisObject.exchange) - if (thisObject.plotterModule.code.icon !== undefined) { - thisObject.plotterTypeIcon = canvas.designSpace.iconCollection.get(thisObject.plotterModule.code.icon) + if (thisObject.plotterModule.config.icon !== undefined) { + thisObject.plotterTypeIcon = canvas.designSpace.iconCollection.get(thisObject.plotterModule.config.icon) } thisObject.baseAssetIcon = getIcon(thisObject.baseAsset) @@ -240,12 +240,12 @@ function newLayer () { } function getIcon (node) { - let nodeDefinition = APP_SCHEMA_MAP.get(node.type) + let nodeDefinition = getNodeDefinition(node) let iconName if (nodeDefinition.alternativeIcons !== undefined) { for (let i = 0; i < nodeDefinition.alternativeIcons.length; i++) { alternativeIcon = nodeDefinition.alternativeIcons[i] - if (alternativeIcon.codeName === node.code.codeName) { + if (alternativeIcon.codeName === node.config.codeName) { iconName = alternativeIcon.iconName } } diff --git a/Panels/PlotterPanel.js b/Panels/PlotterPanel.js index d180560fe..14f1fe5ba 100644 --- a/Panels/PlotterPanel.js +++ b/Panels/PlotterPanel.js @@ -151,24 +151,24 @@ function newPlotterPanel () { } } - if (panelData.code.valueDecimals !== undefined) { + if (panelData.config.valueDecimals !== undefined) { if (value !== undefined) { if (isNaN(value) === false) { - value = value.toFixed(panelData.code.valueDecimals) + value = dynamicDecimals(value, panelData.config.valueDecimals) } } } - if (panelData.code.labelText !== undefined) { - labelText = panelData.code.labelText + if (panelData.config.labelText !== undefined) { + labelText = panelData.config.labelText } - if (panelData.code.labelPosition !== undefined) { - labelPosition = panelData.code.labelPosition + if (panelData.config.labelPosition !== undefined) { + labelPosition = panelData.config.labelPosition } - if (panelData.code.valuePosition !== undefined) { - valuePosition = panelData.code.valuePosition + if (panelData.config.valuePosition !== undefined) { + valuePosition = panelData.config.valuePosition } printLabel(labelText, X_AXIS, UI_PANEL.HEIGHT.NORMAL * labelPosition / 100 / heightFactor, '0.60', undefined, undefined, true, thisObject.container, thisObject.fitFunction) diff --git a/Plotter.js b/Plotter.js index bba22925f..ca72ed893 100644 --- a/Plotter.js +++ b/Plotter.js @@ -277,8 +277,8 @@ function newPlotter () { let record = {} for (let j = 0; j < recordDefinition.properties.length; j++) { let property = recordDefinition.properties[j] - if (property.code.isCalculated !== true) { - record[property.code.codeName] = dataFile[i][j] + if (property.config.isCalculated !== true) { + record[property.config.codeName] = dataFile[i][j] } } @@ -310,7 +310,7 @@ function newPlotter () { timeFrame: timeFrame, ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS } - let variable = {} // This is the structure where the user will define its own variables that will be shared across different code blocks and formulas. + let variable = {} // This is the structure where the user will define its own variables that will be shared across different config blocks and formulas. let results = [] /* This is Initialization Code */ @@ -345,13 +345,13 @@ function newPlotter () { /* For each calculated property we apply its formula */ for (let j = 0; j < recordDefinition.properties.length; j++) { let property = recordDefinition.properties[j] - if (property.code.isCalculated === true) { + if (property.config.isCalculated === true) { if (property.formula !== undefined) { if (property.formula.code !== undefined) { try { let newValue = eval(property.formula.code) let currentRecord = product - currentRecord[property.code.codeName] = newValue + currentRecord[property.config.codeName] = newValue } catch (err) { logger.write('[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. Error = ' + err.stack.stack) logger.write('[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. product = ' + JSON.stringify(product)) @@ -570,23 +570,23 @@ function newPlotter () { let x = 0 let y = 0 eval(point.pointFormula.code) - let dataPoint = { + let rawPoint = { x: x, y: y } - /* Contributing to Auto-Scale */ - coordinateSystem.reportYValue(dataPoint.y) /* The information we store in files is independent from the charing system and its coordinate systems. That means that the first thing we allways need to do is to trasform these points to the coordinate system of the timeline. */ - dataPoint = coordinateSystem.transformThisPoint(dataPoint) + let dataPoint + dataPoint = coordinateSystem.transformThisPoint(rawPoint) dataPoint = transformThisPoint(dataPoint, thisObject.container) dataPoint = canvas.chartingSpace.viewport.fitIntoVisibleArea(dataPoint) dataPoint = thisObject.fitFunction(dataPoint) /* Store the data point at the local map */ + dataPoint.rawPoint = rawPoint dataPoints.set(point.id, dataPoint) } } @@ -598,6 +598,12 @@ function newPlotter () { for (let j = 0; j < productDefinition.referenceParent.shapes.polygons.length; j++) { let polygon = productDefinition.referenceParent.shapes.polygons[j] + /* We will check if we need to plot this Polygon or not. */ + if (polygon.polygonCondition !== undefined) { + let mustPlot = eval(polygon.polygonCondition.code) + if (mustPlot !== true) { continue } + } + let calculatedStyle /* Finding out the fill style */ @@ -616,9 +622,9 @@ function newPlotter () { } else { /* Get the default style if exists */ if (polygon.polygonBody.style !== undefined) { - if (polygon.polygonBody.style.code !== undefined) { - if (polygon.polygonBody.style.code.default !== undefined) { - let bodyStyle = polygon.polygonBody.style.code.default + if (polygon.polygonBody.style.config !== undefined) { + if (polygon.polygonBody.style.config.default !== undefined) { + let bodyStyle = polygon.polygonBody.style.config.default if (bodyStyle.opacity !== undefined) { fillStyle.opacity = bodyStyle.opacity } if (bodyStyle.paletteColor !== undefined) { fillStyle.paletteColor = eval(bodyStyle.paletteColor) } } @@ -631,7 +637,7 @@ function newPlotter () { let value = eval(condition.code) if (value === true) { if (condition.style !== undefined) { - let bodyStyle = condition.style.code + let bodyStyle = condition.style.config if (bodyStyle.opacity !== undefined) { fillStyle.opacity = bodyStyle.opacity } if (bodyStyle.paletteColor !== undefined) { fillStyle.paletteColor = eval(bodyStyle.paletteColor) } } @@ -640,8 +646,8 @@ function newPlotter () { } /* Get the atMousePosition style if exists */ if (polygon.polygonBody.style !== undefined) { - if (polygon.polygonBody.style.code.atMousePosition !== undefined) { - let atMousePositionStyleDefinition = polygon.polygonBody.style.code.atMousePosition + if (polygon.polygonBody.style.config.atMousePosition !== undefined) { + let atMousePositionStyleDefinition = polygon.polygonBody.style.config.atMousePosition let atMousePositionStyle = {} if (atMousePositionStyleDefinition.opacity !== undefined) { atMousePositionStyle.opacity = atMousePositionStyleDefinition.opacity } if (atMousePositionStyleDefinition.paletteColor !== undefined) { atMousePositionStyle.paletteColor = eval(atMousePositionStyleDefinition.paletteColor) } @@ -671,9 +677,9 @@ function newPlotter () { } else { /* Get the default style if exists */ if (polygon.polygonBorder.style !== undefined) { - if (polygon.polygonBorder.style.code !== undefined) { - if (polygon.polygonBorder.style.code.default !== undefined) { - let borderStyle = polygon.polygonBorder.style.code.default + if (polygon.polygonBorder.style.config !== undefined) { + if (polygon.polygonBorder.style.config.default !== undefined) { + let borderStyle = polygon.polygonBorder.style.config.default if (borderStyle.opacity !== undefined) { strokeStyle.opacity = borderStyle.opacity } if (borderStyle.paletteColor !== undefined) { strokeStyle.paletteColor = eval(borderStyle.paletteColor) } if (borderStyle.lineWidth !== undefined) { strokeStyle.lineWidth = borderStyle.lineWidth } @@ -688,7 +694,7 @@ function newPlotter () { let value = eval(condition.code) if (value === true) { if (condition.style !== undefined) { - let borderStyle = condition.style.code + let borderStyle = condition.style.config if (borderStyle.opacity !== undefined) { strokeStyle.opacity = borderStyle.opacity } if (borderStyle.paletteColor !== undefined) { strokeStyle.paletteColor = eval(borderStyle.paletteColor) } if (borderStyle.lineWidth !== undefined) { strokeStyle.lineWidth = borderStyle.lineWidth } @@ -699,8 +705,8 @@ function newPlotter () { } /* Get the atMousePosition style if exists */ if (polygon.polygonBorder.style !== undefined) { - if (polygon.polygonBorder.style.code.atMousePosition !== undefined) { - let atMousePositionStyleDefinition = polygon.polygonBorder.style.code.atMousePosition + if (polygon.polygonBorder.style.config.atMousePosition !== undefined) { + let atMousePositionStyleDefinition = polygon.polygonBorder.style.config.atMousePosition let atMousePositionStyle = {} if (atMousePositionStyleDefinition.opacity !== undefined) { atMousePositionStyle.opacity = atMousePositionStyleDefinition.opacity } if (atMousePositionStyleDefinition.paletteColor !== undefined) { atMousePositionStyle.paletteColor = eval(atMousePositionStyleDefinition.paletteColor) } @@ -724,6 +730,12 @@ function newPlotter () { console.log('[WARN] You have a Polygon Vertex not referencing any Point.') continue } + + /* Contributing to Auto-Scale */ + if (dataPointObject.rawPoint.y > 1 && dataPointObject.rawPoint.y !== undefined && isNaN(dataPointObject.rawPoint.y) === false) { + coordinateSystem.reportYValue(dataPointObject.rawPoint.y) + } + let dataPoint = { x: dataPointObject.x, y: dataPointObject.y diff --git a/PostLoader.js b/PostLoader.js index d47eb8add..82c268bec 100644 --- a/PostLoader.js +++ b/PostLoader.js @@ -29,10 +29,8 @@ function newDashboard () { for (let i = 0; i < APP_SCHEMA_ARRAY.length; i++) { let nodeDefinition = APP_SCHEMA_ARRAY[i] let key = nodeDefinition.type - APP_SCHEMA_MAP.set(key, nodeDefinition) } - startCanvas() } diff --git a/ProductStorage.js b/ProductStorage.js index 68c76ef1b..57c8e6b8a 100644 --- a/ProductStorage.js +++ b/ProductStorage.js @@ -85,7 +85,7 @@ function newProductStorage (name) { for (let i = 0; i < product.datasets.length; i++) { let dataset = product.datasets[i] - switch (dataset.code.type) { + switch (dataset.config.type) { case 'Market Files': { dataSetsToLoad++ @@ -122,7 +122,7 @@ function newProductStorage (name) { } break default: - if (ERROR_LOG === true) { logger.write('[WARN] initialize -> dataset with no type defined or type not supported -> dataset.code.type = ' + dataset.code.type) } + if (ERROR_LOG === true) { logger.write('[WARN] initialize -> dataset with no type defined or type not supported -> dataset.config.type = ' + dataset.config.type) } } function onMarketFileReady (err, pCaller) { diff --git a/Scales/RateScale.js b/Scales/RateScale.js index 6964143fd..93ca0cf9d 100644 --- a/Scales/RateScale.js +++ b/Scales/RateScale.js @@ -255,12 +255,12 @@ function newRateScale () { function saveObjectState () { try { - let code = JSON.parse(thisObject.payload.node.code) - code.minValue = coordinateSystem.min.y - code.maxValue = coordinateSystem.max.y - code.autoMinScale = coordinateSystem.autoMinYScale - code.autoMaxScale = coordinateSystem.autoMaxYScale - thisObject.payload.node.code = JSON.stringify(code, null, 4) + let config = JSON.parse(thisObject.payload.node.config) + config.minValue = coordinateSystem.min.y + config.maxValue = coordinateSystem.max.y + config.autoMinScale = coordinateSystem.autoMinYScale + config.autoMaxScale = coordinateSystem.autoMaxYScale + thisObject.payload.node.config = JSON.stringify(config, null, 4) } catch (err) { // we ignore errors here since most likely they will be parsing errors. } @@ -268,29 +268,29 @@ function newRateScale () { function readObjectState () { try { - let code = JSON.parse(thisObject.payload.node.code) + let config = JSON.parse(thisObject.payload.node.config) if ( - (isNaN(code.minValue) || code.minValue === null || code.minValue === undefined) || - (isNaN(code.maxValue) || code.maxValue === null || code.maxValue === undefined) + (isNaN(config.minValue) || config.minValue === null || config.minValue === undefined) || + (isNaN(config.maxValue) || config.maxValue === null || config.maxValue === undefined) ) { // not using this value } else { if ( - thisObject.minValue !== code.minValue || - thisObject.maxValue !== code.maxValue || - coordinateSystem.autoMinYScale !== code.autoMinScale || - coordinateSystem.autoMaxYScale !== code.autoMaxScale + thisObject.minValue !== config.minValue || + thisObject.maxValue !== config.maxValue || + coordinateSystem.autoMinYScale !== config.autoMinScale || + coordinateSystem.autoMaxYScale !== config.autoMaxScale ) { - thisObject.minValue = code.minValue - thisObject.maxValue = code.maxValue + thisObject.minValue = config.minValue + thisObject.maxValue = config.maxValue coordinateSystem.min.y = thisObject.minValue coordinateSystem.max.y = thisObject.maxValue - if (code.autoMinScale !== undefined && (code.autoMinScale === true || code.autoMinScale === false) && code.autoMaxScale !== undefined && (code.autoMaxScale === true || code.autoMaxScale === false)) { - coordinateSystem.autoMinYScale = code.autoMinScale - coordinateSystem.autoMaxYScale = code.autoMaxScale - autoScaleButton.setStatus(code.autoMinScale, code.autoMaxScale) + if (config.autoMinScale !== undefined && (config.autoMinScale === true || config.autoMinScale === false) && config.autoMaxScale !== undefined && (config.autoMaxScale === true || config.autoMaxScale === false)) { + coordinateSystem.autoMinYScale = config.autoMinScale + coordinateSystem.autoMaxYScale = config.autoMaxScale + autoScaleButton.setStatus(config.autoMinScale, config.autoMaxScale) } coordinateSystem.recalculateScale() diff --git a/Scales/TimeFrameScale.js b/Scales/TimeFrameScale.js index 89fdebc8e..3d0d41cd0 100644 --- a/Scales/TimeFrameScale.js +++ b/Scales/TimeFrameScale.js @@ -313,9 +313,9 @@ function newTimeFrameScale () { function saveObjectState () { try { - let code = JSON.parse(thisObject.payload.node.code) - code.value = timeFrameLabel - thisObject.payload.node.code = JSON.stringify(code) + let config = JSON.parse(thisObject.payload.node.config) + config.value = timeFrameLabel + thisObject.payload.node.config = JSON.stringify(config) } catch (err) { // we ignore errors here since most likely they will be parsing errors. } @@ -323,14 +323,14 @@ function newTimeFrameScale () { function readObjectState () { try { - let code = JSON.parse(thisObject.payload.node.code) - if (code.value !== timeFrameLabel) { + let config = JSON.parse(thisObject.payload.node.config) + if (config.value !== timeFrameLabel) { let found = false for (let i = 0; i < timeFramesMasterArray.length; i++) { let timeFrameArray = timeFramesMasterArray[i] for (let j = 0; j < timeFrameArray.length; j++) { let record = timeFrameArray[j] - if (code.value === record[1]) { + if (config.value === record[1]) { filePeriodIndex = i timeFrameIndex = j found = true diff --git a/Scales/TimeScale.js b/Scales/TimeScale.js index 00d52c530..90ee96fb0 100644 --- a/Scales/TimeScale.js +++ b/Scales/TimeScale.js @@ -172,12 +172,12 @@ function newTimeScale () { function saveObjectState () { try { - let code = JSON.parse(thisObject.payload.node.code) - code.fromDate = (new Date(coordinateSystem.min.x)).toISOString() - code.toDate = (new Date(coordinateSystem.max.x)).toISOString() - code.autoMinScale = coordinateSystem.autoMinXScale - code.autoMaxScale = coordinateSystem.autoMaxXScale - thisObject.payload.node.code = JSON.stringify(code, null, 4) + let config = JSON.parse(thisObject.payload.node.config) + config.fromDate = (new Date(coordinateSystem.min.x)).toISOString() + config.toDate = (new Date(coordinateSystem.max.x)).toISOString() + config.autoMinScale = coordinateSystem.autoMinXScale + config.autoMaxScale = coordinateSystem.autoMaxXScale + thisObject.payload.node.config = JSON.stringify(config, null, 4) } catch (err) { // we ignore errors here since most likely they will be parsing errors. } @@ -185,24 +185,24 @@ function newTimeScale () { function readObjectState () { try { - let code = JSON.parse(thisObject.payload.node.code) + let config = JSON.parse(thisObject.payload.node.config) if ( - (isNaN(Date.parse(code.fromDate)) || code.fromDate === null || code.fromDate === undefined) || - (isNaN(Date.parse(code.toDate)) || code.toDate === null || code.toDate === undefined) + (isNaN(Date.parse(config.fromDate)) || config.fromDate === null || config.fromDate === undefined) || + (isNaN(Date.parse(config.toDate)) || config.toDate === null || config.toDate === undefined) ) { // not using this value } else { - if (thisObject.fromDate !== Date.parse(code.fromDate) || thisObject.toDate !== Date.parse(code.toDate)) { - thisObject.fromDate = Date.parse(code.fromDate) - thisObject.toDate = Date.parse(code.toDate) + if (thisObject.fromDate !== Date.parse(config.fromDate) || thisObject.toDate !== Date.parse(config.toDate)) { + thisObject.fromDate = Date.parse(config.fromDate) + thisObject.toDate = Date.parse(config.toDate) coordinateSystem.min.x = thisObject.fromDate coordinateSystem.max.x = thisObject.toDate - if (code.autoMinScale !== undefined && (code.autoMinScale === true || code.autoMinScale === false) && code.autoMaxScale !== undefined && (code.autoMaxScale === true || code.autoMaxScale === false)) { - coordinateSystem.autoMinXScale = code.autoMinScale - coordinateSystem.autoMaxXScale = code.autoMaxScale - autoScaleButton.setStatus(code.autoMinScale, code.autoMaxScale) + if (config.autoMinScale !== undefined && (config.autoMinScale === true || config.autoMinScale === false) && config.autoMaxScale !== undefined && (config.autoMaxScale === true || config.autoMaxScale === false)) { + coordinateSystem.autoMinXScale = config.autoMinScale + coordinateSystem.autoMaxXScale = config.autoMaxScale + autoScaleButton.setStatus(config.autoMinScale, config.autoMaxScale) } coordinateSystem.recalculateScale() } diff --git a/SideSpace/ListItem.js b/SideSpace/ListItem.js new file mode 100644 index 000000000..59e982979 --- /dev/null +++ b/SideSpace/ListItem.js @@ -0,0 +1,107 @@ +function newListItem () { + const MODULE_NAME = 'List Item' + const ERROR_LOG = true + const logger = newWebDebugLog() + logger.fileName = MODULE_NAME + + let thisObject = { + container: undefined, + fitFunction: undefined, + physics: physics, + draw: draw, + getContainer: getContainer, + initialize: initialize, + finalize: finalize + } + + thisObject.container = newContainer() + thisObject.container.initialize() + thisObject.container.isDraggeable = false + thisObject.container.isWheelable = false + thisObject.container.detectMouseOver = true + thisObject.container.isClickeable = true + thisObject.container.frame.width = SIDE_PANEL_WIDTH * 0.75 + thisObject.container.frame.height = SIDE_PANEL_WIDTH * 0.75 + + let name + let type + + let onMouseOverEventSubscriptionId + let onMouseNotOverEventSubscriptionId + let onMouseClickEventSubscriptionId + + let isMouseOver = false + return thisObject + + function finalize () { + thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId) + thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId) + thisObject.container.eventHandler.stopListening(onMouseClickEventSubscriptionId) + + thisObject.container.finalize() + thisObject.container = undefined + thisObject.fitFunction = undefined + } + + function initialize (pName, pType) { + name = pName + type = pType + + onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver) + onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver) + onMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick) + } + + function getContainer (point) { + if (thisObject.container.frame.isThisPointHere(point, true) === true) { + return thisObject.container + } + } + + function onMouseOver (event) { + isMouseOver = true + } + + function onMouseNotOver () { + isMouseOver = false + } + + function onMouseClick (event) { + canvas.designSpace.workspace.replaceWorkspaceByLoadingOne(name) + } + + function physics () { + + } + + function draw () { + let icon = canvas.designSpace.iconByUiObjectType.get(type) + let backgroundColor = UI_COLOR.BLACK + let labelColor + + const RED_LINE_HIGHT = 4 + const OPACITY = 1 + + let params = { + cornerRadius: 0, + lineWidth: 1, + container: thisObject.container, + borderColor: UI_COLOR.RUSTED_RED, + castShadow: false, + backgroundColor: backgroundColor, + opacity: OPACITY + } + + if (isMouseOver === false) { + labelColor = UI_COLOR.WHITE + } else { + labelColor = UI_COLOR.TITANIUM_YELLOW + } + + roundedCornersBackground(params) + + drawLabel(name, 1 / 2, 3.0 / 10, -5, 0, 15, thisObject.container, labelColor) + drawLabel(type, 1 / 2, 7.2 / 10, -5, 0, 15, thisObject.container, labelColor) + drawIcon(icon, 1 / 2, 1 / 2, 0, 0, 80, thisObject.container) + } +} diff --git a/SideSpace/ListView.js b/SideSpace/ListView.js new file mode 100644 index 000000000..e066f7b73 --- /dev/null +++ b/SideSpace/ListView.js @@ -0,0 +1,271 @@ +function newListView () { + const MODULE_NAME = 'List View' + const ERROR_LOG = true + const logger = newWebDebugLog() + logger.fileName = MODULE_NAME + + let thisObject = { + fitFunction: undefined, + container: undefined, + listItems: [], + payload: undefined, + isVisible: false, + resize: resize, + turnOn: turnOn, + turnOff: turnOff, + physics: physics, + draw: draw, + getContainer: getContainer, + initialize: initialize, + finalize: finalize + } + + thisObject.container = newContainer() + thisObject.container.initialize() + thisObject.container.isDraggeable = false + thisObject.container.isWheelable = true + thisObject.container.detectMouseOver = true + + let isInitialized = false + + let listItemsMap = new Map() + let visibleListItems = [] + let firstVisibleListItem + + let headerHeight = 40 + let footerHeight = 30 + let listItemHeight = SIDE_PANEL_WIDTH * 0.75 + + let posibleVisibleListItems + + let itemSeparation + + let onMouseWheelEventSuscriptionId + + return thisObject + + function finalize () { + thisObject.container.eventHandler.stopListening(onMouseWheelEventSuscriptionId) + + listItemsMap = undefined + visibleListItems = undefined + + thisObject.container.finalize() + thisObject.container = undefined + + thisObject.payload = undefined + thisObject = undefined + } + + function initialize () { + thisObject.container.name = MODULE_NAME + thisObject.container.frame.containerName = thisObject.container.name + thisObject.container.frame.width = SIDE_PANEL_WIDTH * 0.75 + + let position = { // Default position + x: SIDE_PANEL_WIDTH * 0.25 / 2, + y: 20 + } + + thisObject.container.frame.position = position + + onMouseWheelEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel) + + resize() + turnOn() + } + + function resize () { + thisObject.container.frame.height = browserCanvas.height - thisObject.container.frame.position.y * 2 + + let spaceForListItems = (thisObject.container.frame.height - headerHeight - footerHeight) + posibleVisibleListItems = Math.trunc(spaceForListItems / (listItemHeight)) + if ((posibleVisibleListItems - 1) !== 0) { + itemSeparation = (spaceForListItems - listItemHeight * posibleVisibleListItems) / (posibleVisibleListItems - 1) + } else { + itemSeparation = 0 + } + } + + function turnOn () { + firstVisibleListItem = 1 + + callServer(undefined, 'ListWorkspaces', onResponse) + + function onResponse (err, text) { + if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> Could not load the list of your workspaces from the backend. ') } + return + } + + let workspacelist = JSON.parse(text) + thisObject.listItems = [] + for (let i = 0; i < workspacelist.length; i++) { + let workspace = workspacelist[i].replace('.json', '') + let listItem = newListItem() + listItem.initialize(workspace, 'Workspace') + listItem.container.connectToParent(thisObject.container, false, false) + + thisObject.listItems.push(listItem) + } + calculateVisbleListItems() + isInitialized = true + thisObject.isVisible = true + } + } + + function turnOff () { + thisObject.isVisible = false + } + + function onMouseWheel (event) { + delta = event.wheelDelta + if (delta > 0) { + delta = -1 + } else { + delta = 1 + } + + firstVisibleListItem = firstVisibleListItem + delta + + calculateVisbleListItems() + } + + function calculateVisbleListItems () { + let availableSlots = Math.trunc(posibleVisibleListItems) + + if (firstVisibleListItem < 1) { firstVisibleListItem = 1 } + if (firstVisibleListItem > (thisObject.listItems.length - availableSlots + 1)) { firstVisibleListItem = thisObject.listItems.length - availableSlots + 1 } + + visibleListItems = [] + + for (let i = 0; i < thisObject.listItems.length; i++) { + if (i + 1 >= firstVisibleListItem && i + 1 < firstVisibleListItem + availableSlots) { + let listItem = thisObject.listItems[i] + + listItem.container.frame.position.x = 0 + listItem.container.frame.position.y = (listItemHeight + itemSeparation) * visibleListItems.length + headerHeight + + /* Add to Visible Product Array */ + visibleListItems.push(listItem) + } + } + } + + function getContainer (point, purpose) { + if (isInitialized === false || thisObject.isVisible === false) { return } + let container + + /* First we check if thisObject point is inside thisObject space. */ + if (thisObject.container.frame.isThisPointHere(point, true) === true) { + /* Now we see which is the inner most container that has it */ + for (let i = 0; i < visibleListItems.length; i++) { + container = visibleListItems[i].getContainer(point) + + if (container !== undefined) { + if (container.isForThisPurpose(purpose) === true) { + return container + } + } + } + + return thisObject.container + } + } + + function childrenPhysics () { + for (let i = 0; i < thisObject.listItems.length; i++) { + let listItem = thisObject.listItems[i] + listItem.physics() + } + } + + function physics () { + if (isInitialized === false || thisObject.isVisible === false) { return } + if (isInitialized === false) { return } + if (thisObject.isVisible === false) { return } + childrenPhysics() + } + + function draw () { + if (isInitialized === false || thisObject.isVisible === false) { return } + + drawBackground() + drawChildren() + drawScrollBar() + } + + function drawChildren () { + for (let i = 0; i < visibleListItems.length; i++) { + let listItem = visibleListItems[i] + if (listItem !== undefined) { + listItem.draw() + } + } + } + + function drawBackground () { + let label = 'Your Workspaces' + + let backgroundColor = UI_COLOR.WHITE + let params = { + cornerRadius: 5, + lineWidth: 1, + container: thisObject.container, + borderColor: UI_COLOR.RUSTED_RED, + castShadow: false, + backgroundColor: backgroundColor, + opacity: 1 + } + + roundedCornersBackground(params) + + drawLabel(label, 1 / 2, 0, 0, 25, 15, thisObject.container, UI_COLOR.BLACK) + } + + function drawScrollBar () { + if (thisObject.listItems.length > posibleVisibleListItems && posibleVisibleListItems > 0) { + let xOffset = 4 + let barTopPoint = { + x: thisObject.container.frame.width - xOffset, + y: headerHeight + } + let barBottomPoint = { + x: thisObject.container.frame.width - xOffset, + y: thisObject.container.frame.height - footerHeight + } + let ratio = (posibleVisibleListItems * listItemHeight + (posibleVisibleListItems - 1) * itemSeparation) / (thisObject.listItems.length * listItemHeight + (thisObject.listItems.length - 1) * itemSeparation) + let handleHeight = posibleVisibleListItems * (listItemHeight * ratio) + (posibleVisibleListItems - 1) * itemSeparation * ratio + let handleTopPoint = { + x: thisObject.container.frame.width - xOffset, + y: headerHeight + (listItemHeight * ratio * (firstVisibleListItem - 1) + itemSeparation * ratio * (firstVisibleListItem - 1)) + } + let handleBottomPoint = { + x: thisObject.container.frame.width - xOffset, + y: handleTopPoint.y + handleHeight + } + barTopPoint = thisObject.container.frame.frameThisPoint(barTopPoint) + barBottomPoint = thisObject.container.frame.frameThisPoint(barBottomPoint) + handleTopPoint = thisObject.container.frame.frameThisPoint(handleTopPoint) + handleBottomPoint = thisObject.container.frame.frameThisPoint(handleBottomPoint) + + browserCanvasContext.beginPath() + browserCanvasContext.moveTo(barTopPoint.x, barTopPoint.y) + browserCanvasContext.lineTo(barBottomPoint.x, barBottomPoint.y) + browserCanvasContext.closePath() + browserCanvasContext.setLineDash([0, 0]) + browserCanvasContext.lineWidth = 1 + browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREY + ', ' + 1 + ')' + browserCanvasContext.stroke() + + browserCanvasContext.beginPath() + browserCanvasContext.moveTo(handleTopPoint.x, handleTopPoint.y) + browserCanvasContext.lineTo(handleBottomPoint.x, handleBottomPoint.y) + browserCanvasContext.closePath() + browserCanvasContext.setLineDash([0, 0]) + browserCanvasContext.lineWidth = 4 + browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + 1 + ')' + browserCanvasContext.stroke() + } + } +} diff --git a/ControlsToolBox/SidePanelTab.js b/SideSpace/SidePanelTab.js similarity index 81% rename from ControlsToolBox/SidePanelTab.js rename to SideSpace/SidePanelTab.js index 8bd0bd253..1934b2337 100644 --- a/ControlsToolBox/SidePanelTab.js +++ b/SideSpace/SidePanelTab.js @@ -3,6 +3,8 @@ function newSidePanelTab () { let thisObject = { pointerDirection: 'left', container: undefined, + resize: resize, + physics: physics, draw: draw, getContainer: getContainer, initialize: initialize @@ -27,20 +29,27 @@ function newSidePanelTab () { function initialize () { thisObject.container.frame.width = TAB_WIDTH thisObject.container.frame.height = TAB_HEIGHT - thisObject.container.frame.position.x = 0 + thisObject.container.parentContainer.frame.width - thisObject.container.frame.position.y = 20 ORIGINAL_PARENT_POSITON = thisObject.container.parentContainer.frame.position.x thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick) + resize() isInitialized = true } + function resize () { + thisObject.container.frame.position.x = 0 + thisObject.container.parentContainer.frame.width + thisObject.container.frame.position.y = 69 + setClosed() + } + function onMouseClick (event) { if (thisObject.pointerDirection === 'left') { animation = 'opening' + thisObject.container.eventHandler.raiseEvent('opening') } else { animation = 'closing' + thisObject.container.eventHandler.raiseEvent('closing') } } @@ -53,9 +62,13 @@ function newSidePanelTab () { } } - function draw () { + function physics () { if (isInitialized === false) { return } animate() + } + + function draw () { + if (isInitialized === false) { return } borders() arrow() } @@ -66,28 +79,37 @@ function newSidePanelTab () { if (animation === 'opening') { xOffset = xOffset + STEP thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + xOffset - if (xOffset > thisObject.container.parentContainer.frame.width) { - animation = 'none' - xOffset = thisObject.container.parentContainer.frame.width - thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + xOffset - thisObject.container.parentContainer.status = 'visible' - thisObject.pointerDirection = 'right' + if (xOffset >= thisObject.container.parentContainer.frame.width) { + setOpened() + thisObject.container.eventHandler.raiseEvent('opened') } } if (animation === 'closing') { xOffset = xOffset - STEP thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + xOffset - if (xOffset < 0) { - animation = 'none' - xOffset = 0 - thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON - thisObject.container.parentContainer.status = 'hidden' - thisObject.pointerDirection = 'left' + if (xOffset <= 0) { + setClosed() + thisObject.container.eventHandler.raiseEvent('closed') } } } + function setOpened () { + animation = 'none' + xOffset = thisObject.container.parentContainer.frame.width + thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + xOffset + thisObject.container.parentContainer.status = 'visible' + thisObject.pointerDirection = 'right' + } + function setClosed () { + animation = 'none' + xOffset = 0 + thisObject.container.parentContainer.frame.position.x = ORIGINAL_PARENT_POSITON + thisObject.container.parentContainer.status = 'hidden' + thisObject.pointerDirection = 'left' + } + function arrow () { let point1 let point2 @@ -213,4 +235,3 @@ function newSidePanelTab () { browserCanvasContext.stroke() } } - diff --git a/Spaces/ChartingSpace.js b/Spaces/ChartingSpace.js index ae4d6fee0..afbca8ce9 100644 --- a/Spaces/ChartingSpace.js +++ b/Spaces/ChartingSpace.js @@ -92,12 +92,16 @@ function newChartingSpace () { function initialize () { if (isInitialized === true) { return } + if (canvas.designSpace === undefined) { return } + if (canvas.designSpace.workspace === undefined) { return } let rootNodes = canvas.designSpace.workspace.workspaceNode.rootNodes for (let i = 0; i < rootNodes.length; i++) { let rootNode = rootNodes[i] - if (rootNode.type === 'Charting Space') { - thisObject.payload = rootNode.payload + if (rootNode !== null) { + if (rootNode.type === 'Charting Space') { + thisObject.payload = rootNode.payload + } } } @@ -402,6 +406,7 @@ function newChartingSpace () { } function draw () { + if (canWeDraw === false) { return } if (thisObject.visible === false) { return } drawBackground() diff --git a/Spaces/CockpitSpace.js b/Spaces/CockpitSpace.js index 248e07c39..af67991f7 100644 --- a/Spaces/CockpitSpace.js +++ b/Spaces/CockpitSpace.js @@ -20,7 +20,8 @@ physics: physics, getContainer: getContainer, finalize: finalize, - initialize: initialize + initialize: initialize, + initializePosition: initializePosition } thisObject.container = newContainer() @@ -39,6 +40,7 @@ let statusCounter = 0 let statusText let statusType + let isInitilized = false return thisObject @@ -52,6 +54,15 @@ } function initialize () { + canvasBrowserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize) + selfMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick) + + thisObject.fullscreen = newFullScreen() + thisObject.fullscreen.container.connectToParent(thisObject.container) + thisObject.fullscreen.initialize() + } + + function initializePosition () { thisObject.container.frame.position.x = 0 let INITIAL_POSITION @@ -68,13 +79,7 @@ INITIAL_POSITION = 100 thisObject.container.frame.position.y = browserCanvas.height * INITIAL_POSITION / 100 - COCKPIT_SPACE_HEIGHT } - - canvasBrowserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize) - selfMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick) - - thisObject.fullscreen = newFullScreen() - thisObject.fullscreen.container.connectToParent(thisObject.container) - thisObject.fullscreen.initialize() + isInitilized = true } function onMouseClick (event) { @@ -148,6 +153,7 @@ thisObject.fullscreen.physics() } function thisObjectPhysics () { + if (isInitilized === false) { return } /* Check the limits */ thisObject.status = 'MIDDLE' @@ -201,6 +207,7 @@ } function draw () { + if (canWeDraw === false) { return } thisObject.container.frame.draw(false, false) drawBackground() @@ -266,8 +273,10 @@ printLabel(statusText, position.x, position.y, 1, 15, textColor, true, thisObject.container) } - if (canvas.designSpace.workspace.enabled === true && statusText === undefined) { - arrow() + if (canvas.designSpace !== undefined) { + if (canvas.designSpace.workspace.enabled === true && statusText === undefined) { + arrow() + } } } diff --git a/Spaces/DesignSpace.js b/Spaces/DesignSpace.js index db26f42ca..4940727b6 100644 --- a/Spaces/DesignSpace.js +++ b/Spaces/DesignSpace.js @@ -285,7 +285,13 @@ function newDesignSpace () { 'arrangement-vertical-right', 'arrangement-vertical-left', 'arrangement-concave', - 'move-to-phase-event' + 'move-to-phase-event', + 'open-execution', + 'move-order', + 'market-order', + 'limit-order', + 'execution-algorithm', + 'cancel-order' ] for (let i = 0; i < iconsNames.length; i++) { @@ -334,6 +340,7 @@ function newDesignSpace () { } function draw () { + if (canWeDraw === false) { return } if (thisObject.sidePanel !== undefined) { thisObject.sidePanel.draw() } diff --git a/Spaces/FloatingSpace.js b/Spaces/FloatingSpace.js index 7664b7fc5..cb94ebc2d 100644 --- a/Spaces/FloatingSpace.js +++ b/Spaces/FloatingSpace.js @@ -415,6 +415,7 @@ function newFloatingSpace () { } function draw () { + if (canWeDraw === false) { return } if (visible === false) { return } drawBackground() thisObject.floatingLayer.draw() diff --git a/Spaces/PanelsSpace.js b/Spaces/PanelsSpace.js index 28ffa303f..a634fa26e 100644 --- a/Spaces/PanelsSpace.js +++ b/Spaces/PanelsSpace.js @@ -50,14 +50,14 @@ function newPanelsSpace () { } case 'Plotter Panel': { - if (pParameters.panelNode.code.isLegacy !== true) { + if (pParameters.panelNode.config.isLegacy !== true) { panel = newPlotterPanel() panel.fitFunction = canvas.chartingSpace.fitFunction panel.container.isVisibleFunction = canvas.chartingSpace.isThisPointVisible panel.session = pSession panel.initialize(pParameters.panelNode) } else { - panel = getNewPlotterPanel(pParameters.dataMine, pParameters.plotterCodeName, pParameters.moduleCodeName, pParameters.panelNode.code.codeName) + panel = getNewPlotterPanel(pParameters.dataMine, pParameters.plotterCodeName, pParameters.moduleCodeName, pParameters.panelNode.config.codeName) panel.fitFunction = canvas.chartingSpace.fitFunction panel.container.isVisibleFunction = canvas.chartingSpace.isThisPointVisible panel.session = pSession @@ -336,6 +336,7 @@ function newPanelsSpace () { } function draw () { + if (canWeDraw === false) { return } if (thisObject.visible !== true) { return } thisObject.container.frame.draw(false, false) diff --git a/ControlsToolBox/SidePanel.js b/Spaces/SideSpace.js similarity index 66% rename from ControlsToolBox/SidePanel.js rename to Spaces/SideSpace.js index 8c133e6cc..a950c9b7c 100644 --- a/ControlsToolBox/SidePanel.js +++ b/Spaces/SideSpace.js @@ -1,12 +1,13 @@ -function newSidePanel () { - const MODULE_NAME = 'Side Panel' +function newSideSpace () { + const MODULE_NAME = 'Side Space' let thisObject = { - areas: [], sidePanelTab: undefined, container: undefined, + physics: physics, draw: draw, getContainer: getContainer, - initialize: initialize + initialize: initialize, + finalize: finalize } let isInitialized = false @@ -16,9 +17,16 @@ function newSidePanel () { thisObject.container.initialize() thisObject.container.isClickeable = true thisObject.container.isDraggeable = false + thisObject.container.detectMouseOver = true thisObject.container.status = 'hidden' + let listView + resize() + + let openingEventSubscriptionId + let closedEventSubscriptionId + let browserResizedEventSubscriptionId return thisObject function initialize () { @@ -26,21 +34,48 @@ function newSidePanel () { thisObject.sidePanelTab.container.connectToParent(thisObject.container, false, false) thisObject.sidePanelTab.initialize() - canvas.eventHandler.listenToEvent('Browser Resized', resize) + browserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize) + + initializeListView() isInitialized = true } + function finalize () { + canvas.eventHandler.stopListening(browserResizedEventSubscriptionId) + thisObject.sidePanelTab.container.eventHandler.stopListening(openingEventSubscriptionId) + thisObject.sidePanelTab.container.eventHandler.stopListening(closedEventSubscriptionId) + } + + function initializeListView () { + listView = newListView() + listView.initialize() + listView.container.connectToParent(thisObject.container, false, false) + openingEventSubscriptionId = thisObject.sidePanelTab.container.eventHandler.listenToEvent('opening', listView.turnOn) + closedEventSubscriptionId = thisObject.sidePanelTab.container.eventHandler.listenToEvent('closed', listView.turnOff) + } + function resize () { thisObject.container.frame.width = SIDE_PANEL_WIDTH thisObject.container.frame.height = browserCanvas.height // - TOP_SPACE_HEIGHT thisObject.container.frame.position.x = -SIDE_PANEL_WIDTH thisObject.container.frame.position.y = 0 // TOP_SPACE_HEIGHT + + if (listView !== undefined) { + listView.resize() + } + + if (thisObject.sidePanelTab !== undefined) { + thisObject.sidePanelTab.resize() + } } - function getContainer (point) { + function getContainer (point, purpose) { let container - container = thisObject.sidePanelTab.getContainer(point) + container = thisObject.sidePanelTab.getContainer(point, purpose) + if (container !== undefined) { return container } + + container = listView.getContainer(point, purpose) if (container !== undefined) { return container } if (thisObject.container.frame.isThisPointHere(point, true) === true) { @@ -50,15 +85,17 @@ function newSidePanel () { } } + function physics () { + thisObject.sidePanelTab.physics() + listView.physics() + } + function draw () { + if (canWeDraw === false) { return } if (isInitialized === false) { return } borders() thisObject.sidePanelTab.draw() - - for (let i = 0; i < thisObject.areas.length; i++) { - let area = thisObject.areas[i] - area.draw() - } + listView.draw() } function borders () { diff --git a/Spaces/TopSpace.js b/Spaces/TopSpace.js index 905a93894..c88dd2960 100644 --- a/Spaces/TopSpace.js +++ b/Spaces/TopSpace.js @@ -54,6 +54,7 @@ function newTopSpace () { } function draw () { + if (canWeDraw === false) { return } thisObject.container.frame.draw(false, false) drawBackground() @@ -65,7 +66,7 @@ function newTopSpace () { let opacity = 1 browserCanvasContext.beginPath() browserCanvasContext.rect(0, 0, thisObject.container.frame.width, thisObject.container.frame.height) - if (areWeRecording === true) { + if (ARE_WE_RECORDING_A_VIDEO === true) { browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')' } else { browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')' diff --git a/SplashScreen.js b/SplashScreen.js index 4370f934b..34b7c9589 100644 --- a/SplashScreen.js +++ b/SplashScreen.js @@ -13,7 +13,7 @@ function newSplashScreen () { initialize: initialize } - var container = newContainer() + let container = newContainer() container.initialize() thisObject.container = container @@ -31,21 +31,22 @@ function newSplashScreen () { let logo let canDrawLogo = false + let isInitialized = false + let splashScreenNeeded = true return thisObject function initialize () { logo = new Image() - logo.onload = onImageLoad function onImageLoad () { canDrawLogo = true } - logo.src = window.canvasApp.urlPrefix + 'Images/superalgos-logo.png' - canvas.eventHandler.listenToEvent('Browser Resized', resize) + + isInitialized = true } function resize () { @@ -54,6 +55,7 @@ function newSplashScreen () { } function draw () { + if (isInitialized === false) { return } if (splashScreenNeeded === false) { stepsInitializationCounter = 100 canDrawLogo = false @@ -101,6 +103,7 @@ function newSplashScreen () { if (stepsInitializationCounter > 99) { splashScreenNeeded = false + canWeDraw = true stepsInitializationCounter = 99 } @@ -122,7 +125,7 @@ function newSplashScreen () { fontSize = 35 - title = 'Beta 4' + title = 'Beta 5' titlePoint = { x: thisObject.container.frame.width / 2 - title.length / 2 * fontSize * FONT_ASPECT_RATIO - 20, diff --git a/Utilities.js b/Utilities.js index 294c6ec07..4a434bba8 100644 --- a/Utilities.js +++ b/Utilities.js @@ -1,25 +1,6 @@ -function drawContainerBackground (container, color, opacity, fitFunction) { - let fromPoint = { - x: 0, - y: 0 - } - - let toPoint = { - x: container.frame.width, - y: container.frame.height - } - - fromPoint = transformThisPoint(fromPoint, container) - toPoint = transformThisPoint(toPoint, container) - - fromPoint = fitFunction(fromPoint) - toPoint = fitFunction(toPoint) - - browserCanvasContext.beginPath() - browserCanvasContext.rect(fromPoint.x, fromPoint.y, toPoint.x - fromPoint.x, toPoint.y - fromPoint.y) - browserCanvasContext.fillStyle = 'rgba(' + color + ', ' + opacity + ')' - browserCanvasContext.closePath() - browserCanvasContext.fill() +function getNodeDefinition (node) { + let key = node.type + return APP_SCHEMA_MAP.get(key) } function dynamicDecimals (value, minDecimals) { @@ -38,50 +19,6 @@ function dynamicDecimals (value, minDecimals) { return returnValue } -function savePropertyAtNodeConfig (payload, propertyName, value) { - try { - let code = JSON.parse(payload.node.code) - code[propertyName] = value - payload.node.code = JSON.stringify(code, null, 4) - } catch (err) { - // we ignore errors here since most likely they will be parsing errors. - } -} - -function loadPropertyFromNodeConfig (payload, propertyName) { - try { - let code = JSON.parse(payload.node.code) - return code[propertyName] - } catch (err) { - // we ignore errors here since most likely they will be parsing errors. - } -} - -function saveFrame (payload, frame) { - payload.frame = { - position: { - x: frame.position.x, - y: frame.position.y - }, - width: frame.width, - height: frame.height, - radius: frame.radius - } -} - -function loadFrame (payload, frame) { - if (payload.node.savedPayload !== undefined) { - if (payload.node.savedPayload.frame !== undefined) { - frame.position.x = payload.node.savedPayload.frame.position.x - frame.position.y = payload.node.savedPayload.frame.position.y - frame.width = payload.node.savedPayload.frame.width - frame.height = payload.node.savedPayload.frame.height - frame.radius = payload.node.savedPayload.frame.radius - payload.node.savedPayload.frame = undefined - } - } -} - function convertTimeFrameToName (pTimeFrame) { for (let i = 0; i < dailyFilePeriods.length; i++) { let period = dailyFilePeriods[i] @@ -98,52 +35,6 @@ function convertTimeFrameToName (pTimeFrame) { } } -function downloadText (filename, text) { - let element = document.createElement('a') - element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)) - element.setAttribute('download', filename) - element.style.display = 'none' - document.body.appendChild(element) - element.click() - document.body.removeChild(element) -} - -function downloadCanvas (filename) { - let data = browserCanvas.toDataURL('image/png', 1) - /* Change MIME type to trick the browser to downlaod the file instead of displaying it */ - data = data.replace(/^data:image\/[^;]*/, 'data:application/octet-stream') - - /* In addition to 's "download" attribute, you can define HTTP-style headers */ - data = data.replace(/^data:application\/octet-stream/, 'data:application/octet-stream;headers=Content-Disposition%3A%20attachment%3B%20filename=' + filename + '.png') - - let element = document.createElement('a') - element.setAttribute('href', data) - element.setAttribute('download', filename + '.PNG') - element.style.display = 'none' - document.body.appendChild(element) - element.click() - document.body.removeChild(element) -}; - -function transformThisPoint (point, container) { - /* We make the point relative to the current frame */ - - point = container.frame.frameThisPoint(point) - - /* We pass this point through the canvas.chartingSpace.viewport lends, meaning we apply the canvas.chartingSpace.viewport zoom and displacement. */ - - point = canvas.chartingSpace.viewport.transformThisPoint(point) - - return point -} - -function unTransformThisPoint (point, container) { - point = canvas.chartingSpace.viewport.unTransformThisPoint(point) - point = container.frame.unframeThisPoint(point) - - return point -} - function nextPorwerOf10 (number) { for (let i = -10; i <= 10; i++) { if (number < Math.pow(10, i)) { @@ -157,59 +48,6 @@ function pad (str, max) { return str.length < max ? pad('0' + str, max) : str } -function getDateFromPointAtBrowserCanvas (point, container, coordinateSystem) { - point = unTransformThisPoint(point, container) - point = coordinateSystem.unInverseTransform(point, container.frame.height) - - let date = new Date(point.x) - - return date -} - -function getDateFromPointAtChartsSpace (point, container, coordinateSystem) { - point = container.frame.unframeThisPoint(point) - point = coordinateSystem.unInverseTransform(point, container.frame.height) - - let date = new Date(point.x) - - return date -} - -function getDateFromPointAtContainer (point, container, coordinateSystem) { - point = coordinateSystem.unInverseTransform(point, container.frame.height) - - let date = new Date(point.x) - - return date -} - -function getRateFromPointAtBrowserCanvas (point, container, coordinateSystem) { - point = unTransformThisPoint(point, container) - point = coordinateSystem.unInverseTransform(point, container.frame.height) - - return point.y -} - -function getRateFromPointAtChartingSpace (point, container, coordinateSystem) { - point = container.frame.unframeThisPoint(point) - point = coordinateSystem.unInverseTransform(point, container.frame.height) - - return point.y -} - -function getRateFromPointAtContainer (point, container, coordinateSystem) { - point = coordinateSystem.unInverseTransform(point, container.frame.height) - - return point.y -} - -function getMilisecondsFromPoint (point, container, coordinateSystem) { - point = unTransformThisPoint(point, container) - point = coordinateSystem.unInverseTransform(point, container.frame.height) - - return point.x -} - function moveToUserPosition (container, currentDate, currentRate, coordinateSystem, ignoreX, ignoreY, mousePosition, fitFunction) { let targetPoint = { x: currentDate.valueOf(), @@ -244,50 +82,6 @@ function removeTime (datetime) { return dateOnly } -function printLabel (labelToPrint, x, y, opacity, fontSize, color, center, container, fitFunction, noDecimals, fixedDecimals) { - if (labelToPrint === undefined) { return } - let labelPoint - if (color === undefined) { color = UI_COLOR.DARK } - if (fontSize === undefined) { fontSize = 10 }; - - browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY - let label = labelToPrint - if (isNaN(label) === false && label !== '') { - if (fixedDecimals !== true) { - label = dynamicDecimals(labelToPrint) - } - label = label.toLocaleString() - if (noDecimals === true) { - label = Math.trunc(label) - } - } - - let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO - - if (center === true) { - labelPoint = { - x: x - xOffset, - y: y - } - } else { - labelPoint = { - x: x, - y: y - } - } - - if (container !== undefined) { - labelPoint = container.frame.frameThisPoint(labelPoint) - } - - if (fitFunction !== undefined) { - labelPoint = fitFunction(labelPoint) - } - - browserCanvasContext.fillStyle = 'rgba(' + color + ', ' + opacity + ')' - browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y) -} - function newUniqueId () { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8) diff --git a/Utilities/CoordinateTransformations.js b/Utilities/CoordinateTransformations.js new file mode 100644 index 000000000..9f3f9444d --- /dev/null +++ b/Utilities/CoordinateTransformations.js @@ -0,0 +1,18 @@ +function transformThisPoint (point, container) { + /* We make the point relative to the current frame */ + + point = container.frame.frameThisPoint(point) + + /* We pass this point through the canvas.chartingSpace.viewport lends, meaning we apply the canvas.chartingSpace.viewport zoom and displacement. */ + + point = canvas.chartingSpace.viewport.transformThisPoint(point) + + return point +} + +function unTransformThisPoint (point, container) { + point = canvas.chartingSpace.viewport.unTransformThisPoint(point) + point = container.frame.unframeThisPoint(point) + + return point +} diff --git a/Utilities/DateRateTransformations.js b/Utilities/DateRateTransformations.js new file mode 100644 index 000000000..196c99ecc --- /dev/null +++ b/Utilities/DateRateTransformations.js @@ -0,0 +1,53 @@ +function getDateFromPointAtBrowserCanvas (point, container, coordinateSystem) { + point = unTransformThisPoint(point, container) + point = coordinateSystem.unInverseTransform(point, container.frame.height) + + let date = new Date(point.x) + + return date +} + +function getDateFromPointAtChartsSpace (point, container, coordinateSystem) { + point = container.frame.unframeThisPoint(point) + point = coordinateSystem.unInverseTransform(point, container.frame.height) + + let date = new Date(point.x) + + return date +} + +function getDateFromPointAtContainer (point, container, coordinateSystem) { + point = coordinateSystem.unInverseTransform(point, container.frame.height) + + let date = new Date(point.x) + + return date +} + +function getRateFromPointAtBrowserCanvas (point, container, coordinateSystem) { + point = unTransformThisPoint(point, container) + point = coordinateSystem.unInverseTransform(point, container.frame.height) + + return point.y +} + +function getRateFromPointAtChartingSpace (point, container, coordinateSystem) { + point = container.frame.unframeThisPoint(point) + point = coordinateSystem.unInverseTransform(point, container.frame.height) + + return point.y +} + +function getRateFromPointAtContainer (point, container, coordinateSystem) { + point = coordinateSystem.unInverseTransform(point, container.frame.height) + + return point.y +} + +function getMilisecondsFromPoint (point, container, coordinateSystem) { + point = unTransformThisPoint(point, container) + point = coordinateSystem.unInverseTransform(point, container.frame.height) + + return point.x +} + diff --git a/Utilities/Download.js b/Utilities/Download.js new file mode 100644 index 000000000..39e8e3884 --- /dev/null +++ b/Utilities/Download.js @@ -0,0 +1,58 @@ +function downloadText (filename, text) { + let element = document.createElement('a') + element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)) + element.setAttribute('download', filename) + element.style.display = 'none' + document.body.appendChild(element) + element.click() + document.body.removeChild(element) +} + +function downloadCanvas (filename, canvasToUse) { + let data = canvasToUse.toDataURL('image/png', 1) + /* Change MIME type to trick the browser to downlaod the file instead of displaying it */ + data = data.replace(/^data:image\/[^;]*/, 'data:application/octet-stream') + + /* In addition to 's "download" attribute, you can define HTTP-style headers */ + data = data.replace(/^data:application\/octet-stream/, 'data:application/octet-stream;headers=Content-Disposition%3A%20attachment%3B%20filename=' + filename + '.png') + + let element = document.createElement('a') + element.setAttribute('href', data) + element.setAttribute('download', filename + '.PNG') + element.style.display = 'none' + document.body.appendChild(element) + element.click() + document.body.removeChild(element) +}; + +function downloadPanorama (filename) { + let INITIAL_WIDTH = 800 + let FINAL_WIDTH = browserCanvas.width - INITIAL_WIDTH + + if (ARE_WE_RECORDING_A_MARKET_PANORAMA === false) { + /* We start recording the panorame. */ + ARE_WE_RECORDING_A_MARKET_PANORAMA = true + marketPanoramaCanvas = document.createElement('canvas') + marketPanoramaCanvas.width = INITIAL_WIDTH * 50 + marketPanoramaCanvas.height = browserCanvas.height + marketPanoramaCanvas.getContext('2d').drawImage(browserCanvas, 0, 0, INITIAL_WIDTH, browserCanvas.height, 0, 0, INITIAL_WIDTH, browserCanvas.height) + CURRENT_PANORAMA_POSITION = INITIAL_WIDTH + } else { + /* We stop recording and download the resulting image. */ + ARE_WE_RECORDING_A_MARKET_PANORAMA = false + marketPanoramaCanvas.getContext('2d').drawImage(browserCanvas, browserCanvas.width - FINAL_WIDTH, 0, FINAL_WIDTH, browserCanvas.height, CURRENT_PANORAMA_POSITION, 0, FINAL_WIDTH, browserCanvas.height) + let finalResultCanvas = document.createElement('canvas') + finalResultCanvas.width = CURRENT_PANORAMA_POSITION + FINAL_WIDTH + finalResultCanvas.height = browserCanvas.height + finalResultCanvas.getContext('2d').drawImage(marketPanoramaCanvas, 0, 0, finalResultCanvas.width, browserCanvas.height, 0, 0, finalResultCanvas.width, browserCanvas.height) + downloadCanvas(filename, finalResultCanvas) + marketPanoramaCanvas = undefined + } +} + +function addToMarketPanorama () { + let SECTION_WIDTH = 80 * 2 + let INITIAL_POSITION = 800 - SECTION_WIDTH + marketPanoramaCanvas.getContext('2d').drawImage(browserCanvas, INITIAL_POSITION, 0, SECTION_WIDTH, browserCanvas.height, CURRENT_PANORAMA_POSITION, 0, SECTION_WIDTH, browserCanvas.height) + CURRENT_PANORAMA_POSITION = CURRENT_PANORAMA_POSITION + SECTION_WIDTH +} diff --git a/Utilities/RoundedCornersBackground.js b/Utilities/DrawPrint.js similarity index 77% rename from Utilities/RoundedCornersBackground.js rename to Utilities/DrawPrint.js index 825400009..4e38f2a0c 100644 --- a/Utilities/RoundedCornersBackground.js +++ b/Utilities/DrawPrint.js @@ -150,3 +150,72 @@ function drawIcon (icon, xFactor, yFactor, xOffset, yOffset, imageSize, containe } } } + +function drawContainerBackground (container, color, opacity, fitFunction) { + let fromPoint = { + x: 0, + y: 0 + } + + let toPoint = { + x: container.frame.width, + y: container.frame.height + } + + fromPoint = transformThisPoint(fromPoint, container) + toPoint = transformThisPoint(toPoint, container) + + fromPoint = fitFunction(fromPoint) + toPoint = fitFunction(toPoint) + + browserCanvasContext.beginPath() + browserCanvasContext.rect(fromPoint.x, fromPoint.y, toPoint.x - fromPoint.x, toPoint.y - fromPoint.y) + browserCanvasContext.fillStyle = 'rgba(' + color + ', ' + opacity + ')' + browserCanvasContext.closePath() + browserCanvasContext.fill() +} + +function printLabel (labelToPrint, x, y, opacity, fontSize, color, center, container, fitFunction, noDecimals, fixedDecimals) { + if (labelToPrint === undefined) { return } + let labelPoint + if (color === undefined) { color = UI_COLOR.DARK } + if (fontSize === undefined) { fontSize = 10 }; + + browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY + let label = labelToPrint + if (isNaN(label) === false && label !== '') { + if (fixedDecimals !== true) { + label = dynamicDecimals(labelToPrint) + } + label = label.toLocaleString() + if (noDecimals === true) { + label = Math.trunc(label) + } + } + + let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO + + if (center === true) { + labelPoint = { + x: x - xOffset, + y: y + } + } else { + labelPoint = { + x: x, + y: y + } + } + + if (container !== undefined) { + labelPoint = container.frame.frameThisPoint(labelPoint) + } + + if (fitFunction !== undefined) { + labelPoint = fitFunction(labelPoint) + } + + browserCanvasContext.fillStyle = 'rgba(' + color + ', ' + opacity + ')' + browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y) +} + diff --git a/Utilities/LoadSaveFrame.js b/Utilities/LoadSaveFrame.js new file mode 100644 index 000000000..5bda8c98b --- /dev/null +++ b/Utilities/LoadSaveFrame.js @@ -0,0 +1,24 @@ +function saveFrame (payload, frame) { + payload.frame = { + position: { + x: frame.position.x, + y: frame.position.y + }, + width: frame.width, + height: frame.height, + radius: frame.radius + } +} + +function loadFrame (payload, frame) { + if (payload.node.savedPayload !== undefined) { + if (payload.node.savedPayload.frame !== undefined) { + frame.position.x = payload.node.savedPayload.frame.position.x + frame.position.y = payload.node.savedPayload.frame.position.y + frame.width = payload.node.savedPayload.frame.width + frame.height = payload.node.savedPayload.frame.height + frame.radius = payload.node.savedPayload.frame.radius + payload.node.savedPayload.frame = undefined + } + } +} diff --git a/Utilities/NodeConfig.js b/Utilities/NodeConfig.js new file mode 100644 index 000000000..482e1ae3e --- /dev/null +++ b/Utilities/NodeConfig.js @@ -0,0 +1,18 @@ +function savePropertyAtNodeConfig (payload, propertyName, value) { + try { + let config = JSON.parse(payload.node.config) + config[propertyName] = value + payload.node.config = JSON.stringify(config, null, 4) + } catch (err) { + // we ignore errors here since most likely they will be parsing errors. + } +} + +function loadPropertyFromNodeConfig (payload, propertyName) { + try { + let config = JSON.parse(payload.node.config) + return config[propertyName] + } catch (err) { + // we ignore errors here since most likely they will be parsing errors. + } +}