diff --git a/BackendServers/WebServer/AppLoader.js b/BackendServers/WebServer/AppLoader.js index fd1ac76e4..f038011dc 100644 --- a/BackendServers/WebServer/AppLoader.js +++ b/BackendServers/WebServer/AppLoader.js @@ -63,8 +63,9 @@ function newAppLoader() { 'Panels/PlotterPanel.js', 'Panels/PanelsVisibleButton.js', - 'ControlsToolBox/SidePanel.js', - 'ControlsToolBox/SidePanelTab.js', + 'SideSpace/SidePanelTab.js', + 'SideSpace/ListView.js', + 'SideSpace/ListItem.js', 'Spaces/CockpitSpace.js', 'Spaces/TopSpace.js', @@ -72,6 +73,7 @@ function newAppLoader() { 'Spaces/ChartingSpace.js', 'Spaces/FloatingSpace.js', 'Spaces/DesignSpace.js', + 'Spaces/SideSpace.js', 'Files/SingleFile.js', 'Files/FileCloud.js', diff --git a/BackendServers/WebServer/Images/superalgos-header-background ORIGINAL.png b/BackendServers/WebServer/Images/superalgos-header-background ORIGINAL.png new file mode 100644 index 000000000..5c980aa38 Binary files /dev/null and b/BackendServers/WebServer/Images/superalgos-header-background ORIGINAL.png differ diff --git a/BackendServers/WebServer/Images/superalgos-header-background.png b/BackendServers/WebServer/Images/superalgos-header-background.png index 5c980aa38..fe2c14c0d 100644 Binary files a/BackendServers/WebServer/Images/superalgos-header-background.png and b/BackendServers/WebServer/Images/superalgos-header-background.png differ diff --git a/BackendServers/webServer.js b/BackendServers/webServer.js index 0dad1a7a8..a09892e33 100644 --- a/BackendServers/webServer.js +++ b/BackendServers/webServer.js @@ -435,6 +435,12 @@ exports.newWebServer = function newWebServer(EVENTS_SERVER) { } break + case 'SideSpace': + { + respondWithFile(process.env.PATH_TO_CANVAS_APP + '/' + requestParameters[1] + '/' + requestParameters[2], response) + } + break + case 'AppSchema.js': { let fs = require('fs') @@ -492,14 +498,17 @@ exports.newWebServer = function newWebServer(EVENTS_SERVER) { if (err) { if (CONSOLE_LOG === true) { console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath) } respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response) + return } else { - respondWithContent(fileList, response) + respondWithContent(JSON.stringify(fileList), response) + return } } } catch (err) { if (CONSOLE_LOG === true) { console.log('[ERROR] Error reading a directory content. filePath = ' + dirPath) } respondWithContent(JSON.stringify(global.DEFAULT_FAIL_RESPONSE), response) + return } } diff --git a/CanvasApp/Animation.js b/CanvasApp/Animation.js index 1e06c4849..cab8a470c 100644 --- a/CanvasApp/Animation.js +++ b/CanvasApp/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/CanvasApp/Canvas.js b/CanvasApp/Canvas.js index 51ad14431..8a2cfaa4f 100644 --- a/CanvasApp/Canvas.js +++ b/CanvasApp/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 @@ -121,10 +121,10 @@ function newCanvas () { 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() } @@ -574,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) { @@ -589,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) { @@ -600,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) { @@ -616,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) { @@ -636,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) { @@ -694,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) + 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) { @@ -703,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) { @@ -712,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) { @@ -721,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) { @@ -730,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) { @@ -833,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) + + 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) @@ -930,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) { @@ -937,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) { @@ -946,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) @@ -959,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/CanvasApp/ChartingSpace/EdgeEditor.js b/CanvasApp/ChartingSpace/EdgeEditor.js index 6932fa58b..134d0006f 100644 --- a/CanvasApp/ChartingSpace/EdgeEditor.js +++ b/CanvasApp/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/CanvasApp/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js b/CanvasApp/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js index 992a37b8f..4a56efdc2 100644 --- a/CanvasApp/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js +++ b/CanvasApp/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js @@ -14,7 +14,7 @@ function newUiObjectsFromNodes () { return thisObject - function recreateWorkspace (node, replacingCurrentWorkspace) { + function recreateWorkspace (node, replacingCurrentWorkspace, callBackFunction) { mapOfNodes = new Map() tasksToRun = [] sessionsToRun = [] @@ -145,6 +145,10 @@ function newUiObjectsFromNodes () { // We give a few seconds for the tasks to start setTimeout(runSessions, 10000) } + + if (callBackFunction !== undefined) { + callBackFunction() // The recreation of the workspace is complete + } } } diff --git a/CanvasApp/DesignSpace/Workspace/Workspace.js b/CanvasApp/DesignSpace/Workspace/Workspace.js index f50e50f4d..710f90310 100644 --- a/CanvasApp/DesignSpace/Workspace/Workspace.js +++ b/CanvasApp/DesignSpace/Workspace/Workspace.js @@ -94,23 +94,26 @@ function newWorkspace () { 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. - finishInitialization() + recreateWorkspace() return } thisObject.workspaceNode = JSON.parse(text) - finishInitialization() + recreateWorkspace() } } else { thisObject.workspaceNode = getWorkspace() // This is the default workspace that comes with the system. - finishInitialization() + recreateWorkspace() + } + + function recreateWorkspace () { + functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode, false, finishInitialization) } function finishInitialization () { - functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode) setupEventsServerClients() thisObject.enabled = true canvas.cockpitSpace.initializePosition() - + canvas.splashScreen.initialize() setInterval(saveWorkspace, 60000) } } catch (err) { @@ -195,7 +198,9 @@ function newWorkspace () { if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result) { window.localStorage.setItem('Last Used Workspace', workspace.name) window.localStorage.setItem('Session Timestamp', sessionTimestamp) - canvas.cockpitSpace.setStatus(workspace.name + ' Saved.', 50, canvas.cockpitSpace.statusTypes.ALL_GOOD) + 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) } diff --git a/CanvasApp/Globals.js b/CanvasApp/Globals.js index cc1ec296a..92038622b 100644 --- a/CanvasApp/Globals.js +++ b/CanvasApp/Globals.js @@ -222,7 +222,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/CanvasApp/SideSpace/ListItem.js b/CanvasApp/SideSpace/ListItem.js new file mode 100644 index 000000000..6e4ec6885 --- /dev/null +++ b/CanvasApp/SideSpace/ListItem.js @@ -0,0 +1,72 @@ +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 + + return thisObject + + function finalize () { + thisObject.container.finalize() + thisObject.container = undefined + thisObject.fitFunction = undefined + } + + function initialize () { + + } + + function getContainer (point) { + if (thisObject.container.frame.isThisPointHere(point, true) === true) { + return thisObject.container + } + } + + function onMouseClick (event) { + + } + + function physics () { + + } + + function draw () { + let label1 = 'TEST NAME' + + let backgroundColor = UI_COLOR.BLACK + + const RED_LINE_HIGHT = 4 + const OPACITY = 0.75 + + let params = { + cornerRadius: 0, + lineWidth: 1, + container: thisObject.container, + borderColor: UI_COLOR.RUSTED_RED, + castShadow: false, + backgroundColor: backgroundColor, + opacity: OPACITY + } + + roundedCornersBackground(params) + + drawLabel(label1, 1 / 2, 6 / 10, -5, 0, label1FontSize, thisObject.container) + drawIcon(thisObject.exchangeIcon, 1 / 8, 2 / 10, 0, 0, 14, thisObject.container) + } +} diff --git a/CanvasApp/SideSpace/ListView.js b/CanvasApp/SideSpace/ListView.js new file mode 100644 index 000000000..8c8097671 --- /dev/null +++ b/CanvasApp/SideSpace/ListView.js @@ -0,0 +1,285 @@ +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, + 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 = 1 + + const LAYER_SEPARATION = 0 + + let headerHeight = 40 + let footerHeight = 10 + let listItemHeight = 70 + let desiredVisibleListItems = 5 + let posibleVisibleListItems = 5 + let desiredObjectHeight = (listItemHeight + LAYER_SEPARATION) * desiredVisibleListItems + headerHeight + footerHeight + let posibleObjectHeight = (listItemHeight + LAYER_SEPARATION) * posibleVisibleListItems + headerHeight + footerHeight + + let onMouseWheelEventSuscriptionId + let onMouseOverEventSubscriptionId + let onMouseNotOverEventSubscriptionId + + let isMouseOver + return thisObject + + function finalize () { + thisObject.container.eventHandler.stopListening(onMouseWheelEventSuscriptionId) + thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId) + thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId) + + 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.80 + thisObject.container.frame.height = headerHeight + + let position = { // Default position + x: SIDE_PANEL_WIDTH * 0.10, + y: 20 + } + + thisObject.container.frame.position = position + + onMouseWheelEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel) + onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver) + onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver) + + 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) + for (let i = 0; i < workspacelist.length; i++) { + let workspace = workspacelist[i] + let listItem = newListItem() + listItem.initialize() + listItem.container.connectToParent(thisObject.container, false, false) + thisObject.listItems.push(listItem) + } + isInitialized = true + } + } + + function onMouseOver (event) { + isMouseOver = true + } + + function onMouseNotOver () { + isMouseOver = false + } + + function onMouseWheel (event) { + delta = event.wheelDelta + if (delta > 0) { + delta = -1 + } else { + delta = 1 + } + + if (event.y - thisObject.container.frame.position.y - CURRENT_TOP_MARGIN < headerHeight) { // Mouse wheel over the header, not a listItem + desiredVisibleListItems = desiredVisibleListItems + delta + if (desiredVisibleListItems < 0) { desiredVisibleListItems = 0 } + if (desiredVisibleListItems > thisObject.listItems.length) { desiredVisibleListItems = thisObject.listItems.length } + } else { + firstVisibleListItem = firstVisibleListItem + delta + } + desiredObjectHeight = (listItemHeight + LAYER_SEPARATION) * desiredVisibleListItems + headerHeight + footerHeight + calculateVisbleListItems() + } + + function calculateVisbleListItems () { + let availableSlots = 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 + LAYER_SEPARATION) * visibleListItems.length + headerHeight + + /* Add to Visible Product Array */ + visibleListItems.push(listItem) + } + } + } + + function getContainer (point, purpose) { + if (isInitialized === false || thisObject.visible === false || thisObject.isHidden === true) { return } + let container + + if (isMouseOver === true && purpose !== GET_CONTAINER_PURPOSE.MOUSE_OVER) { + container = thisObject.upDownButton.getContainer(point) + if (container !== undefined) { return container } + + container = thisObject.leftRightButton.getContainer(point) + if (container !== undefined) { return 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) { + let checkPoint = { + x: point.x, + y: point.y + } + + checkPoint = thisObject.fitFunction(checkPoint) + + if (point.x === checkPoint.x && point.y === checkPoint.y) { + if (purpose !== GET_CONTAINER_PURPOSE.MOUSE_OVER) { + return container + } + } + } + } + + /* The point does not belong to any inner container, so we return the current container. */ + let checkPoint = { + x: point.x, + y: point.y + } + + checkPoint = thisObject.fitFunction(checkPoint) + + if (point.x === checkPoint.x && point.y === checkPoint.y) { + 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) { return } + if (thisObject.isVisible === false) { return } + childrenPhysics() + } + + function draw () { + if (isInitialized === false || thisObject.visible === false) { return } + + drawHeader() + drawScrollBar() + } + + function drawHeader () { + let label1 = 'HEADER' + + let icon1 = canvas.designSpace.iconByUiObjectType.get('Workspace') + + 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(label1, 1 / 2, 0, 0, 15, 9, thisObject.container, UI_COLOR.BLACK) + drawIcon(icon1, 1 / 8, 0, 0, 20, 28, thisObject.container) + } + + 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 / thisObject.listItems.length + let handleHeight = (posibleVisibleListItems * (listItemHeight + LAYER_SEPARATION)) * ratio + let handleTopPoint = { + x: thisObject.container.frame.width - xOffset, + y: headerHeight + (listItemHeight + LAYER_SEPARATION) * 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/CanvasApp/ControlsToolBox/SidePanelTab.js b/CanvasApp/SideSpace/SidePanelTab.js similarity index 97% rename from CanvasApp/ControlsToolBox/SidePanelTab.js rename to CanvasApp/SideSpace/SidePanelTab.js index 8bd0bd253..c415b1046 100644 --- a/CanvasApp/ControlsToolBox/SidePanelTab.js +++ b/CanvasApp/SideSpace/SidePanelTab.js @@ -3,6 +3,7 @@ function newSidePanelTab () { let thisObject = { pointerDirection: 'left', container: undefined, + physics: physics, draw: draw, getContainer: getContainer, initialize: initialize @@ -28,7 +29,7 @@ function newSidePanelTab () { 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 + thisObject.container.frame.position.y = 69 ORIGINAL_PARENT_POSITON = thisObject.container.parentContainer.frame.position.x @@ -53,9 +54,13 @@ function newSidePanelTab () { } } - function draw () { + function physics () { if (isInitialized === false) { return } animate() + } + + function draw () { + if (isInitialized === false) { return } borders() arrow() } diff --git a/CanvasApp/Spaces/ChartingSpace.js b/CanvasApp/Spaces/ChartingSpace.js index 91568cacf..afbca8ce9 100644 --- a/CanvasApp/Spaces/ChartingSpace.js +++ b/CanvasApp/Spaces/ChartingSpace.js @@ -92,6 +92,8 @@ 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++) { @@ -404,6 +406,7 @@ function newChartingSpace () { } function draw () { + if (canWeDraw === false) { return } if (thisObject.visible === false) { return } drawBackground() diff --git a/CanvasApp/Spaces/CockpitSpace.js b/CanvasApp/Spaces/CockpitSpace.js index ed8cfb932..af67991f7 100644 --- a/CanvasApp/Spaces/CockpitSpace.js +++ b/CanvasApp/Spaces/CockpitSpace.js @@ -207,6 +207,7 @@ } function draw () { + if (canWeDraw === false) { return } thisObject.container.frame.draw(false, false) drawBackground() @@ -272,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/CanvasApp/Spaces/DesignSpace.js b/CanvasApp/Spaces/DesignSpace.js index db26f42ca..305e1d532 100644 --- a/CanvasApp/Spaces/DesignSpace.js +++ b/CanvasApp/Spaces/DesignSpace.js @@ -334,6 +334,7 @@ function newDesignSpace () { } function draw () { + if (canWeDraw === false) { return } if (thisObject.sidePanel !== undefined) { thisObject.sidePanel.draw() } diff --git a/CanvasApp/Spaces/FloatingSpace.js b/CanvasApp/Spaces/FloatingSpace.js index 7664b7fc5..cb94ebc2d 100644 --- a/CanvasApp/Spaces/FloatingSpace.js +++ b/CanvasApp/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/CanvasApp/Spaces/PanelsSpace.js b/CanvasApp/Spaces/PanelsSpace.js index 28ffa303f..e752631d1 100644 --- a/CanvasApp/Spaces/PanelsSpace.js +++ b/CanvasApp/Spaces/PanelsSpace.js @@ -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/CanvasApp/ControlsToolBox/SidePanel.js b/CanvasApp/Spaces/SideSpace.js similarity index 85% rename from CanvasApp/ControlsToolBox/SidePanel.js rename to CanvasApp/Spaces/SideSpace.js index 8c133e6cc..66366c11a 100644 --- a/CanvasApp/ControlsToolBox/SidePanel.js +++ b/CanvasApp/Spaces/SideSpace.js @@ -1,9 +1,9 @@ -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 @@ -16,8 +16,11 @@ function newSidePanel () { thisObject.container.initialize() thisObject.container.isClickeable = true thisObject.container.isDraggeable = false + thisObject.container.detectMouseOver = true thisObject.container.status = 'hidden' + let listView + resize() return thisObject @@ -27,9 +30,17 @@ function newSidePanel () { thisObject.sidePanelTab.initialize() canvas.eventHandler.listenToEvent('Browser Resized', resize) + + initializeListView() isInitialized = true } + function initializeListView () { + listView = newListView() + listView.initialize() + listView.container.connectToParent(thisObject.container, false, false) + } + function resize () { thisObject.container.frame.width = SIDE_PANEL_WIDTH thisObject.container.frame.height = browserCanvas.height // - TOP_SPACE_HEIGHT @@ -43,6 +54,9 @@ function newSidePanel () { container = thisObject.sidePanelTab.getContainer(point) if (container !== undefined) { return container } + container = listView.getContainer(point) + if (container !== undefined) { return container } + if (thisObject.container.frame.isThisPointHere(point, true) === true) { return thisObject.container } else { @@ -50,15 +64,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/CanvasApp/Spaces/TopSpace.js b/CanvasApp/Spaces/TopSpace.js index 905a93894..c88dd2960 100644 --- a/CanvasApp/Spaces/TopSpace.js +++ b/CanvasApp/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/CanvasApp/SplashScreen.js b/CanvasApp/SplashScreen.js index 55508957f..34b7c9589 100644 --- a/CanvasApp/SplashScreen.js +++ b/CanvasApp/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 } diff --git a/CanvasApp/Utilities.js b/CanvasApp/Utilities.js index 294c6ec07..2af862981 100644 --- a/CanvasApp/Utilities.js +++ b/CanvasApp/Utilities.js @@ -108,8 +108,8 @@ function downloadText (filename, text) { document.body.removeChild(element) } -function downloadCanvas (filename) { - let data = browserCanvas.toDataURL('image/png', 1) +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') @@ -125,6 +125,38 @@ function downloadCanvas (filename) { 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 +} + function transformThisPoint (point, container) { /* We make the point relative to the current frame */