67 files changed
+5472
-16565
No files matched your search
+4
-11
@@ -57,21 +57,14 @@ function newAnimation () {
|
||||
function animationLoop () {
|
||||
try {
|
||||
if (window.canvasApp.visible === true) {
|
||||
/* We set the canvas to its normal width and height */
|
||||
|
||||
/* We set the canvas to its normal width and height */
|
||||
browserCanvas.width = window.innerWidth
|
||||
browserCanvas.height = window.innerHeight - CURRENT_TOP_MARGIN
|
||||
|
||||
/* First thing is to clear the actual canvas */
|
||||
|
||||
clearBrowserCanvas()
|
||||
|
||||
/* Let reset the current chart that is on focus */
|
||||
|
||||
window.CHART_ON_FOCUS = ''
|
||||
|
||||
/* We loop through the callback functions collections and execute them all. */
|
||||
/* First thing is to clear the actual canvas */
|
||||
// clearBrowserCanvas()
|
||||
|
||||
/* We loop through the callback functions collections and execute them all. */
|
||||
let performanceMap = new Map()
|
||||
let totalTimeConsumed = 0
|
||||
let totalElements = 0
|
||||
|
||||
@@ -120,18 +120,16 @@ function newCanvas () {
|
||||
animation.addCallBackFunction('System Event Handler Physics', systemEventHandler.physics)
|
||||
|
||||
/* Spcaces Physics */
|
||||
animation.addCallBackFunction('CockpitSpace Physics', thisObject.cockpitSpace.physics)
|
||||
animation.addCallBackFunction('Floating Space Physics', thisObject.floatingSpace.physics)
|
||||
animation.addCallBackFunction('Chart Space Physics', thisObject.chartSpace.physics)
|
||||
animation.addCallBackFunction('CockpitSpace Physics', thisObject.cockpitSpace.physics)
|
||||
animation.addCallBackFunction('Strategy Space Physics', thisObject.designerSpace.physics)
|
||||
animation.addCallBackFunction('Panels Space Physics', thisObject.panelsSpace.physics)
|
||||
|
||||
/* Spcaces Drawing */
|
||||
animation.addCallBackFunction('Floating Space Draw', thisObject.floatingSpace.draw)
|
||||
animation.addCallBackFunction('Chart Space Background', thisObject.chartSpace.drawBackground)
|
||||
animation.addCallBackFunction('Chart Space Draw', thisObject.chartSpace.draw)
|
||||
animation.addCallBackFunction('Panels Space', thisObject.panelsSpace.draw)
|
||||
animation.addCallBackFunction('ViewPort Animate', viewPort.animate)
|
||||
animation.addCallBackFunction('CockpitSpace Draw', thisObject.cockpitSpace.draw)
|
||||
animation.addCallBackFunction('Designer Space Draw', thisObject.designerSpace.draw)
|
||||
animation.addCallBackFunction('Top Space Draw', thisObject.topSpace.draw)
|
||||
@@ -145,9 +143,7 @@ function newCanvas () {
|
||||
function initializeBrowserCanvas () {
|
||||
try {
|
||||
browserCanvasContext = browserCanvas.getContext('2d')
|
||||
browserCanvasContext.font = 'Saira'
|
||||
|
||||
viewPort.initialize()
|
||||
browserCanvasContext.font = 'Saira Condensed'
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initializeBrowserCanvas -> err = ' + err.stack) }
|
||||
}
|
||||
@@ -155,11 +151,12 @@ function newCanvas () {
|
||||
|
||||
function addCanvasEvents () {
|
||||
try {
|
||||
canvas.eventHandler.listenToEvent('Browser Resized', browserResized)
|
||||
|
||||
/* Keyboard events */
|
||||
window.addEventListener('keydown', onKeyDown, true)
|
||||
|
||||
/* Mouse Events */
|
||||
|
||||
browserCanvas.addEventListener('mousedown', onMouseDown, false)
|
||||
browserCanvas.addEventListener('mouseup', onMouseUp, false)
|
||||
browserCanvas.addEventListener('mousemove', onMouseMove, false)
|
||||
@@ -172,7 +169,6 @@ function newCanvas () {
|
||||
} else browserCanvas.attachEvent('onmousewheel', onMouseWheel)// IE 6/7/8
|
||||
|
||||
/* Dragging Files Over the Canvas */
|
||||
|
||||
browserCanvas.addEventListener('dragenter', onDragEnter, false)
|
||||
browserCanvas.addEventListener('dragleave', onDragLeave, false)
|
||||
browserCanvas.addEventListener('dragover', onDragOver, false)
|
||||
@@ -187,6 +183,17 @@ function newCanvas () {
|
||||
}
|
||||
}
|
||||
|
||||
function browserResized () {
|
||||
try {
|
||||
browserCanvas = document.getElementById('canvas')
|
||||
|
||||
browserCanvas.width = window.innerWidth
|
||||
browserCanvas.height = window.innerHeight - CURRENT_TOP_MARGIN
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] browserResized -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
function onKeyDown (event) {
|
||||
let nodeOnFocus = canvas.designerSpace.workspace.getNodeThatIsOnFocus()
|
||||
if (nodeOnFocus !== undefined) {
|
||||
@@ -501,7 +508,7 @@ function newCanvas () {
|
||||
container = thisObject.chartSpace.getContainer(point)
|
||||
|
||||
if (container !== undefined) {
|
||||
if (container.isDraggeable === true) {
|
||||
if (container.isDraggeable === true && event.button === 2) {
|
||||
containerBeingDragged = container
|
||||
containerDragStarted = true
|
||||
containerBeingDragged.eventHandler.raiseEvent('onDragStarted', point)
|
||||
@@ -624,8 +631,10 @@ function newCanvas () {
|
||||
y: event.pageY - CURRENT_TOP_MARGIN
|
||||
}
|
||||
|
||||
viewPort.mousePosition.x = point.x
|
||||
viewPort.mousePosition.y = point.y
|
||||
if (canvas.chartSpace.viewport !== undefined) {
|
||||
canvas.chartSpace.viewport.mousePosition.x = point.x
|
||||
canvas.chartSpace.viewport.mousePosition.y = point.y
|
||||
}
|
||||
|
||||
if (containerDragStarted === true || floatingObjectDragStarted === true || viewPortBeingDragged === true) {
|
||||
if (floatingObjectDragStarted === true) {
|
||||
@@ -655,9 +664,8 @@ function newCanvas () {
|
||||
dragVector.upY = point.y
|
||||
|
||||
checkDrag(event)
|
||||
} else {
|
||||
onMouseOver(event)
|
||||
}
|
||||
onMouseOver(event)
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] onMouseMove -> err = ' + err.stack) }
|
||||
}
|
||||
@@ -665,8 +673,16 @@ function newCanvas () {
|
||||
|
||||
function onMouseOver (event) {
|
||||
try {
|
||||
/* Then we check who is the current object underneeth the mounse. */
|
||||
if (containerDragStarted === true) {
|
||||
let point = {
|
||||
x: event.pageX,
|
||||
y: event.pageY - CURRENT_TOP_MARGIN
|
||||
}
|
||||
containerBeingDragged.eventHandler.raiseEvent('onMouseOver', point)
|
||||
return
|
||||
}
|
||||
|
||||
/* Then we check who is the current object underneeth the mounse. */
|
||||
let point = {
|
||||
x: event.pageX,
|
||||
y: event.pageY - CURRENT_TOP_MARGIN
|
||||
@@ -674,8 +690,7 @@ function newCanvas () {
|
||||
|
||||
let container
|
||||
|
||||
/* We check if the mouse is over an element of the Strategy Space / */
|
||||
|
||||
/* We check if the mouse is over an element of the Strategy Space / */
|
||||
if (thisObject.designerSpace !== undefined) {
|
||||
container = thisObject.designerSpace.getContainer(point)
|
||||
|
||||
@@ -685,8 +700,7 @@ function newCanvas () {
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 / */
|
||||
if (thisObject.topSpace !== undefined) {
|
||||
container = thisObject.topSpace.getContainer(point)
|
||||
|
||||
@@ -696,8 +710,7 @@ function newCanvas () {
|
||||
}
|
||||
}
|
||||
|
||||
/* We check if the mouse is over an element of the CockpitSpace / */
|
||||
|
||||
/* We check if the mouse is over an element of the CockpitSpace / */
|
||||
if (thisObject.cockpitSpace !== undefined) {
|
||||
container = thisObject.cockpitSpace.getContainer(point)
|
||||
|
||||
@@ -707,8 +720,7 @@ function newCanvas () {
|
||||
}
|
||||
}
|
||||
|
||||
/* We check if the mouse is over a panel/ */
|
||||
|
||||
/* We check if the mouse is over a panel/ */
|
||||
if (thisObject.panelsSpace !== undefined) {
|
||||
container = thisObject.panelsSpace.getContainer(point)
|
||||
|
||||
@@ -718,8 +730,7 @@ function newCanvas () {
|
||||
}
|
||||
}
|
||||
|
||||
/* If it is not, then we check if it is over any of the existing containers at the Chart Space. */
|
||||
|
||||
/* If it is not, then we check if it is over any of the existing containers at the Chart Space. */
|
||||
if (thisObject.chartSpace !== undefined) {
|
||||
container = thisObject.chartSpace.getContainer(point, GET_CONTAINER_PURPOSE.MOUSE_OVER)
|
||||
|
||||
@@ -745,7 +756,6 @@ function newCanvas () {
|
||||
lastContainerMouseOver.eventHandler.raiseEvent('onMouseNotOver', point)
|
||||
}
|
||||
}
|
||||
|
||||
container.eventHandler.raiseEvent('onMouseOver', point)
|
||||
lastContainerMouseOver = container
|
||||
}
|
||||
@@ -758,7 +768,7 @@ function newCanvas () {
|
||||
try {
|
||||
// cross-browser wheel delta
|
||||
var event = window.event || event // old IE support
|
||||
let delta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail))
|
||||
event.delta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail))
|
||||
|
||||
/* We try first with panels. */
|
||||
|
||||
@@ -794,7 +804,7 @@ function newCanvas () {
|
||||
}
|
||||
|
||||
if (container !== undefined) {
|
||||
viewPort.applyZoom(delta)
|
||||
canvas.chartSpace.viewport.onMouseWheel(event)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -850,32 +860,36 @@ function newCanvas () {
|
||||
thisObject.eventHandler.raiseEvent('Dragging', undefined)
|
||||
|
||||
if (containerDragStarted || viewPortBeingDragged) {
|
||||
/* The parameters received have been captured with zoom applied. We must remove the zoom in order to correctly modify the displacement. */
|
||||
|
||||
let downCopy = {
|
||||
x: dragVector.downX,
|
||||
y: dragVector.downY
|
||||
}
|
||||
|
||||
let downCopyNoTransf
|
||||
downCopyNoTransf = viewPort.unzoomThisPoint(downCopy)
|
||||
// downCopyNoTransf = containerBeingDragged.zoom.unzoomThisPoint(downCopyNoTransf);
|
||||
|
||||
let upCopy = {
|
||||
x: dragVector.upX,
|
||||
y: dragVector.upY
|
||||
}
|
||||
|
||||
let upCopyNoTranf
|
||||
upCopyNoTranf = viewPort.unzoomThisPoint(upCopy)
|
||||
|
||||
let displaceVector = {
|
||||
x: dragVector.upX - dragVector.downX,
|
||||
y: dragVector.upY - dragVector.downY
|
||||
}
|
||||
|
||||
if (containerBeingDragged !== undefined && containerBeingDragged.insideViewport === true) {
|
||||
let downCopy = {
|
||||
x: dragVector.downX,
|
||||
y: dragVector.downY
|
||||
}
|
||||
|
||||
let downNoZoom
|
||||
downNoZoom = canvas.chartSpace.viewport.unTransformThisPoint(downCopy)
|
||||
|
||||
let upCopy = {
|
||||
x: dragVector.upX,
|
||||
y: dragVector.upY
|
||||
}
|
||||
|
||||
let upNoZoom
|
||||
upNoZoom = canvas.chartSpace.viewport.unTransformThisPoint(upCopy)
|
||||
|
||||
displaceVector = {
|
||||
x: upNoZoom.x - downNoZoom.x,
|
||||
y: upNoZoom.y - downNoZoom.y
|
||||
}
|
||||
}
|
||||
|
||||
if (viewPortBeingDragged) {
|
||||
viewPort.displace(displaceVector)
|
||||
canvas.chartSpace.viewport.displace(displaceVector)
|
||||
}
|
||||
|
||||
if (containerBeingDragged !== undefined) {
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
|
||||
function getSideDays (timePeriod) {
|
||||
function getSideDays (timeFrame) {
|
||||
let daysOnSides
|
||||
|
||||
if (timePeriod < _1_HOUR_IN_MILISECONDS) {
|
||||
if (timeFrame < _1_HOUR_IN_MILISECONDS) {
|
||||
daysOnSides = 1
|
||||
}
|
||||
|
||||
if (timePeriod === _1_HOUR_IN_MILISECONDS) {
|
||||
if (timeFrame === _1_HOUR_IN_MILISECONDS) {
|
||||
daysOnSides = 9
|
||||
}
|
||||
|
||||
if (timePeriod === _2_HOURS_IN_MILISECONDS) {
|
||||
if (timeFrame === _2_HOURS_IN_MILISECONDS) {
|
||||
daysOnSides = 10
|
||||
}
|
||||
|
||||
if (timePeriod === _3_HOURS_IN_MILISECONDS) {
|
||||
if (timeFrame === _3_HOURS_IN_MILISECONDS) {
|
||||
daysOnSides = 12
|
||||
}
|
||||
|
||||
if (timePeriod === _4_HOURS_IN_MILISECONDS) {
|
||||
if (timeFrame === _4_HOURS_IN_MILISECONDS) {
|
||||
daysOnSides = 20
|
||||
}
|
||||
|
||||
if (timePeriod === _6_HOURS_IN_MILISECONDS) {
|
||||
if (timeFrame === _6_HOURS_IN_MILISECONDS) {
|
||||
daysOnSides = 35
|
||||
}
|
||||
|
||||
if (timePeriod === _8_HOURS_IN_MILISECONDS) {
|
||||
if (timeFrame === _8_HOURS_IN_MILISECONDS) {
|
||||
daysOnSides = 44
|
||||
}
|
||||
|
||||
if (timePeriod === _12_HOURS_IN_MILISECONDS) {
|
||||
if (timeFrame === _12_HOURS_IN_MILISECONDS) {
|
||||
daysOnSides = 56
|
||||
}
|
||||
|
||||
if (timePeriod === ONE_DAY_IN_MILISECONDS) {
|
||||
if (timeFrame === ONE_DAY_IN_MILISECONDS) {
|
||||
daysOnSides = 154
|
||||
}
|
||||
|
||||
return daysOnSides
|
||||
}
|
||||
|
||||
function getCondenseFactor (timePeriod) {
|
||||
switch (timePeriod) {
|
||||
function getCondenseFactor (timeFrame) {
|
||||
switch (timeFrame) {
|
||||
case _1_MINUTE_IN_MILISECONDS: return 1
|
||||
case _5_MINUTES_IN_MILISECONDS: return 5
|
||||
case _10_MINUTES_IN_MILISECONDS: return 10
|
||||
@@ -51,8 +51,8 @@ function getCondenseFactor (timePeriod) {
|
||||
}
|
||||
}
|
||||
|
||||
function getTransparenceFactor (timePeriod) {
|
||||
switch (timePeriod) {
|
||||
function getTransparenceFactor (timeFrame) {
|
||||
switch (timeFrame) {
|
||||
case _1_MINUTE_IN_MILISECONDS: return '0.12'
|
||||
case _5_MINUTES_IN_MILISECONDS: return '0.10'
|
||||
case _10_MINUTES_IN_MILISECONDS: return '0.08'
|
||||
@@ -62,82 +62,78 @@ function getTransparenceFactor (timePeriod) {
|
||||
}
|
||||
|
||||
function recalculatePeriod (zoomLevel) {
|
||||
// console.log(" recalculatePeriod > " + zoomLevel);
|
||||
|
||||
if (zoomLevel > 200) {
|
||||
// console.log('NEW ZOOM LEVEL', zoomLevel)
|
||||
if (zoomLevel > 400) {
|
||||
return _1_MINUTE_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > 120) {
|
||||
if (zoomLevel > 360) {
|
||||
return _2_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > 80) {
|
||||
if (zoomLevel > 330) {
|
||||
return _3_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > 60) {
|
||||
if (zoomLevel > 300) {
|
||||
return _4_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > 15) {
|
||||
if (zoomLevel > 270) {
|
||||
return _5_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -7) {
|
||||
if (zoomLevel > 250) {
|
||||
return _10_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -10) {
|
||||
if (zoomLevel > 230) {
|
||||
return _15_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -13) {
|
||||
if (zoomLevel > 210) {
|
||||
return _20_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -15) {
|
||||
if (zoomLevel > 190) {
|
||||
return _30_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -16) {
|
||||
if (zoomLevel > 170) {
|
||||
return _40_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -17) {
|
||||
if (zoomLevel > 150) {
|
||||
return _45_MINUTES_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -18) {
|
||||
if (zoomLevel > 130) {
|
||||
return _1_HOUR_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -24) {
|
||||
if (zoomLevel > 110) {
|
||||
return _2_HOURS_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -25) {
|
||||
if (zoomLevel > 80) {
|
||||
return _3_HOURS_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -27) {
|
||||
if (zoomLevel > 50) {
|
||||
return _4_HOURS_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -27.5) {
|
||||
if (zoomLevel > 35) {
|
||||
return _6_HOURS_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -27.75) {
|
||||
if (zoomLevel > 20) {
|
||||
return _8_HOURS_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel > -28) {
|
||||
if (zoomLevel > 10) {
|
||||
return _12_HOURS_IN_MILISECONDS
|
||||
}
|
||||
|
||||
if (zoomLevel <= -28) {
|
||||
return ONE_DAY_IN_MILISECONDS
|
||||
}
|
||||
return ONE_DAY_IN_MILISECONDS
|
||||
}
|
||||
@@ -7,65 +7,75 @@ The scale on the Y axis depends on the data that wants to be plotted. Usually we
|
||||
|
||||
*/
|
||||
|
||||
function newTimeLineCoordinateSystem () {
|
||||
function newCoordinateSystem () {
|
||||
let thisObject = {
|
||||
min: undefined,
|
||||
max: undefined,
|
||||
maxHeight: undefined,
|
||||
maxWidth: undefined,
|
||||
scale: undefined,
|
||||
eventHandler: undefined,
|
||||
recalculateScale: recalculateScale,
|
||||
transformThisPoint: transformThisPoint,
|
||||
transformThisPoint2: transformThisPoint2,
|
||||
unInverseTransform: unInverseTransform,
|
||||
inverseTransformUncappedY: inverseTransformUncappedY,
|
||||
initializeX: initializeX,
|
||||
initializeY: initializeY,
|
||||
initialize: initialize
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
var min = {
|
||||
thisObject.min = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
thisObject.max = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
thisObject.scale = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
var max = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
var scale = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.min = min
|
||||
thisObject.max = max
|
||||
thisObject.scale = scale
|
||||
|
||||
let maxHeight
|
||||
thisObject.eventHandler = newEventHandler()
|
||||
thisObject.eventHandler.name = 'Coordinate System'
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize (minValue, maxValue, maxWidth, pMaxHeight) {
|
||||
/* Defines the min and max value of rate that we are going to transport to the available screen at the center position. */
|
||||
function finalize () {
|
||||
thisObject.eventHandler.finalize()
|
||||
thisObject.eventHandler = undefined
|
||||
}
|
||||
|
||||
function initialize (minValue, maxValue, pMaxWidth, pMaxHeight) {
|
||||
/* Defines the min and max value of rate that we are going to transport to the available screen at the center position. */
|
||||
thisObject.min.x = minValue.x // * 0.999; // 0.1% less
|
||||
thisObject.max.x = maxValue.x // * 1.001; // 0.1% more
|
||||
|
||||
thisObject.min.y = minValue.y // * 0.999; // 0.1% less
|
||||
thisObject.max.y = maxValue.y // * 1.001; // 0.1% more
|
||||
|
||||
/* Defines the initial Zoom level at center position. */
|
||||
thisObject.maxWidth = pMaxWidth
|
||||
thisObject.maxHeight = pMaxHeight
|
||||
|
||||
thisObject.scale.x = maxWidth / (thisObject.max.x - thisObject.min.x)
|
||||
thisObject.scale.y = pMaxHeight / (thisObject.max.y - thisObject.min.y)
|
||||
recalculateScale()
|
||||
}
|
||||
|
||||
maxHeight = pMaxHeight
|
||||
function recalculateScale () {
|
||||
/* Defines the initial Zoom level at center position. */
|
||||
thisObject.scale.x = thisObject.maxWidth / (thisObject.max.x - thisObject.min.x)
|
||||
thisObject.scale.y = thisObject.maxHeight / (thisObject.max.y - thisObject.min.y)
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Scale Changed')
|
||||
}
|
||||
|
||||
function initializeX (minValue, maxValue, maxWidth) {
|
||||
thisObject.min.x = minValue.x // * 0.999; // 0.1% less
|
||||
thisObject.max.x = maxValue.x // * 1.001; // 0.1% more
|
||||
|
||||
thisObject.scale.x = maxWidth / (thisObject.max.x - thisObject.min.x)
|
||||
thisObject.scale.x = thisObject.maxWidth / (thisObject.max.x - thisObject.min.x)
|
||||
}
|
||||
|
||||
function initializeY (minValue, maxValue, pMaxHeight) {
|
||||
@@ -74,7 +84,7 @@ function newTimeLineCoordinateSystem () {
|
||||
|
||||
thisObject.scale.y = pMaxHeight / (thisObject.max.y - thisObject.min.y)
|
||||
|
||||
maxHeight = pMaxHeight
|
||||
thisObject.maxHeight = pMaxHeight
|
||||
}
|
||||
|
||||
function transformThisPoint (point) {
|
||||
@@ -92,8 +102,8 @@ function newTimeLineCoordinateSystem () {
|
||||
*/
|
||||
|
||||
point = {
|
||||
x: (point.x - this.min.x) * this.scale.x,
|
||||
y: maxHeight - (point.y - this.min.y) * this.scale.y
|
||||
x: (point.x - thisObject.min.x) * thisObject.scale.x,
|
||||
y: thisObject.maxHeight - (point.y - thisObject.min.y) * thisObject.scale.y
|
||||
}
|
||||
|
||||
return point
|
||||
@@ -101,8 +111,8 @@ function newTimeLineCoordinateSystem () {
|
||||
|
||||
function transformThisPoint2 (point) {
|
||||
point = {
|
||||
x: (point.x - this.min.x) * this.scale.x,
|
||||
y: (maxHeight - point.y - this.min.y) * this.scale.y
|
||||
x: (point.x - thisObject.min.x) * thisObject.scale.x,
|
||||
y: (thisObject.maxHeight - point.y - thisObject.min.y) * thisObject.scale.y
|
||||
}
|
||||
|
||||
return point
|
||||
@@ -110,8 +120,8 @@ function newTimeLineCoordinateSystem () {
|
||||
|
||||
function unInverseTransform (point, inverseY) {
|
||||
point = {
|
||||
x: (point.x / this.scale.x) + this.min.x,
|
||||
y: (inverseY - point.y) / this.scale.y + this.min.y
|
||||
x: (point.x / thisObject.scale.x) + thisObject.min.x,
|
||||
y: (inverseY - point.y) / thisObject.scale.y + thisObject.min.y
|
||||
}
|
||||
|
||||
return point
|
||||
@@ -119,11 +129,10 @@ function newTimeLineCoordinateSystem () {
|
||||
|
||||
function inverseTransformUncappedY (point, inverseY) {
|
||||
point = {
|
||||
x: (point.x - this.min.x) * this.scale.x,
|
||||
y: (inverseY - point.y) * this.scale.y
|
||||
x: (point.x - thisObject.min.x) * thisObject.scale.x,
|
||||
y: (inverseY - point.y) * thisObject.scale.y
|
||||
}
|
||||
|
||||
return point
|
||||
}
|
||||
}
|
||||
|
||||
+182
-224
@@ -4,28 +4,29 @@ function newPlottersManager () {
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let productPlotters = []
|
||||
|
||||
let timePeriod = INITIAL_TIME_PERIOD
|
||||
let timeFrame = INITIAL_TIME_PERIOD
|
||||
let datetime = NEW_SESSION_INITIAL_DATE
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
container: undefined,
|
||||
payload: undefined,
|
||||
connectors: [],
|
||||
setDatetime: setDatetime,
|
||||
setTimePeriod: setTimePeriod,
|
||||
positionAtDatetime: positionAtDatetime,
|
||||
setTimeFrame: setTimeFrame,
|
||||
setCoordinateSystem: setCoordinateSystem,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let initializationReady = false
|
||||
thisObject.connectors = []
|
||||
|
||||
let productsPanel
|
||||
let exchange
|
||||
let market
|
||||
let initializationReady = false
|
||||
let layersPanel
|
||||
let onLayerStatusChangedEventSuscriptionId
|
||||
let coordinateSystem
|
||||
|
||||
setupContainer()
|
||||
return thisObject
|
||||
@@ -36,304 +37,261 @@ function newPlottersManager () {
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
for (let i = 0; i < productPlotters.length; i++) {
|
||||
layersPanel.container.eventHandler.stopListening(onLayerStatusChangedEventSuscriptionId)
|
||||
layersPanel = undefined
|
||||
|
||||
for (let i = 0; i < thisObject.connectors.length; i++) {
|
||||
let connector = thisObject.connectors[i]
|
||||
/* Then the panels. */
|
||||
for (let j = 0; j < productPlotters[i].panels.length; j++) {
|
||||
canvas.panelsSpace.destroyPanel(productPlotters[i].panels[j])
|
||||
productPlotters[i].panels[j] = undefined
|
||||
for (let j = 0; j < connector.panels.length; j++) {
|
||||
canvas.panelsSpace.destroyPanel(connector.panels[j])
|
||||
connector.panels[j] = undefined
|
||||
}
|
||||
productPlotters[i].panels = undefined
|
||||
connector.panels = undefined
|
||||
|
||||
/* Finalize the plotters */
|
||||
if (productPlotters[i].plotter.finalize !== undefined) {
|
||||
productPlotters[i].plotter.finalize()
|
||||
if (connector.plotter.finalize !== undefined) {
|
||||
connector.plotter.container.eventHandler.stopListening(connector.plotter.onRecordChangeEventsSubscriptionId)
|
||||
connector.plotter.finalize()
|
||||
}
|
||||
productPlotters[i].plotter = undefined
|
||||
connector.plotter = undefined
|
||||
|
||||
/* Finally the Storage Objects */
|
||||
productPlotters[i].storage.finalize()
|
||||
productPlotters[i].storage = undefined
|
||||
finalizeStorage(connector.storage)
|
||||
connector.storage = undefined
|
||||
|
||||
productPlotters[i] = undefined
|
||||
connector = undefined
|
||||
}
|
||||
productPlotters = []
|
||||
|
||||
productsPanel = undefined
|
||||
thisObject.connectors = []
|
||||
coordinateSystem = undefined
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
setupContainer()
|
||||
thisObject.payload = undefined
|
||||
}
|
||||
|
||||
function initialize (pProductsPanel, pExchange, pMarket, callBackFunction) {
|
||||
try {
|
||||
/* Remember the Products Panel */
|
||||
productsPanel = pProductsPanel
|
||||
exchange = pExchange
|
||||
market = pMarket
|
||||
/* Listen to the event of change of status */
|
||||
productsPanel.container.eventHandler.listenToEvent('Product Card Status Changed', onProductCardStatusChanged)
|
||||
|
||||
/* Lets get all the cards that needs to be loaded. */
|
||||
|
||||
let initializationCounter = 0
|
||||
let loadingProductCards = productsPanel.getLoadingProductCards()
|
||||
let okCounter = 0
|
||||
let failCounter = 0
|
||||
|
||||
if (loadingProductCards.length === 0) {
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
return
|
||||
}
|
||||
for (let i = 0; i < loadingProductCards.length; i++) {
|
||||
/* For each one, we will initialize the associated plotter. */
|
||||
initializeProductPlotter(loadingProductCards[i], onProductPlotterInitialized)
|
||||
|
||||
function onProductPlotterInitialized (err) {
|
||||
initializationCounter++
|
||||
|
||||
switch (err.result) {
|
||||
case GLOBAL.DEFAULT_OK_RESPONSE.result: {
|
||||
okCounter++
|
||||
break
|
||||
}
|
||||
case GLOBAL.DEFAULT_FAIL_RESPONSE.result: {
|
||||
failCounter++
|
||||
break
|
||||
}
|
||||
default: {
|
||||
failCounter++
|
||||
break
|
||||
}
|
||||
}
|
||||
if (initializationCounter === loadingProductCards.length) {
|
||||
// This was the last one.
|
||||
/* If less than 50% of plotters are initialized then we return FAIL. */
|
||||
if (okCounter >= 1) {
|
||||
initializationReady = true
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
} else {
|
||||
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) }
|
||||
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
function finalizeStorage (storage) {
|
||||
storage.eventHandler.stopListening(storage.onMarketFileLoadedLayerEventsSubscriptionId)
|
||||
storage.eventHandler.stopListening(storage.onDailyFileLoadedLayerEventsSubscriptionId)
|
||||
storage.eventHandler.stopListening(storage.onSingleFileLoadedLayerEventsSubscriptionId)
|
||||
storage.eventHandler.stopListening(storage.onFileSequenceLoadedLayerEventsSubscriptionId)
|
||||
storage.eventHandler.stopListening(storage.onDailyFileLoadedPlotterEventsSubscriptionId)
|
||||
storage.finalize()
|
||||
}
|
||||
|
||||
function initializeProductPlotter (pProductCard, callBack) {
|
||||
function initialize (pLayersPanel) {
|
||||
/* Remember the Layers Panel */
|
||||
layersPanel = pLayersPanel
|
||||
|
||||
/* Listen to the event of change of status */
|
||||
onLayerStatusChangedEventSuscriptionId = layersPanel.container.eventHandler.listenToEvent('Layer Status Changed', onLayerStatusChanged)
|
||||
}
|
||||
|
||||
function initializePlotter (layer) {
|
||||
try {
|
||||
/* Before Initializing a Plotter, we need the Storage it will use, loaded with the files it will initially need. */
|
||||
let objName = pProductCard.devTeam.codeName + '-' + pProductCard.bot.codeName + '-' + pProductCard.product.codeName
|
||||
let storage = newProductStorage(objName)
|
||||
/*
|
||||
/* Before Initializing a Plotter, we need the Storage it will use, loaded with the files it will initially need. */
|
||||
let storage = newProductStorage(layer.payload.node.id)
|
||||
|
||||
Before Initializing the Storage, we will put the Product Card to listen to the events the storage will raise every time a file is loaded,
|
||||
so that the UI can somehow show this. There are different types of events.
|
||||
/*
|
||||
Before Initializing the Storage, we will put the Layer to listen to the events the storage will raise every time a file is loaded,
|
||||
so that the UI can somehow show this. There are different types of events.
|
||||
*/
|
||||
for (let i = 0; i < layer.definition.referenceParent.referenceParent.datasets.length; i++) {
|
||||
let dataset = layer.definition.referenceParent.referenceParent.datasets[i]
|
||||
|
||||
*/
|
||||
for (let i = 0; i < pProductCard.product.dataSets.length; i++) {
|
||||
let thisSet = pProductCard.product.dataSets[i]
|
||||
|
||||
switch (thisSet.type) {
|
||||
switch (dataset.code.type) {
|
||||
case 'Market Files': {
|
||||
storage.eventHandler.listenToEvent('Market File Loaded', pProductCard.onMarketFileLoaded)
|
||||
storage.onMarketFileLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('Market File Loaded', layer.onMarketFileLoaded)
|
||||
}
|
||||
break
|
||||
case 'Daily Files': {
|
||||
storage.eventHandler.listenToEvent('Daily File Loaded', pProductCard.onDailyFileLoaded)
|
||||
storage.onDailyFileLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('Daily File Loaded', layer.onDailyFileLoaded)
|
||||
}
|
||||
break
|
||||
case 'Single File': {
|
||||
storage.eventHandler.listenToEvent('Single File Loaded', pProductCard.onSingleFileLoaded)
|
||||
storage.onSingleFileLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('Single File Loaded', layer.onSingleFileLoaded)
|
||||
}
|
||||
break
|
||||
case 'File Sequence': {
|
||||
storage.eventHandler.listenToEvent('File Sequence Loaded', pProductCard.onFileSequenceLoaded)
|
||||
storage.onFileSequenceLoadedLayerEventsSubscriptionId = storage.eventHandler.listenToEvent('File Sequence Loaded', layer.onFileSequenceLoaded)
|
||||
}
|
||||
break
|
||||
default: {
|
||||
if (ERROR_LOG === true) {
|
||||
logger.write('[ERROR] initializePlotter -> Dataset Type Incorrect or Undefined -> dataset.type = ' + dataset.type)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
storage.initialize(pProductCard.devTeam, pProductCard.bot, pProductCard.session, pProductCard.product, exchange, market, datetime, timePeriod, onProductStorageInitialized)
|
||||
let baseAsset = layer.definition.referenceParent.parentNode.referenceParent.baseAsset.referenceParent.code.codeName
|
||||
let quotedAsset = layer.definition.referenceParent.parentNode.referenceParent.quotedAsset.referenceParent.code.codeName
|
||||
let market = {
|
||||
baseAsset: baseAsset,
|
||||
quotedAsset: quotedAsset
|
||||
}
|
||||
let product = layer.definition.referenceParent.referenceParent
|
||||
let bot = layer.definition.referenceParent.referenceParent.parentNode
|
||||
let dataMine = layer.definition.referenceParent.referenceParent.parentNode.parentNode
|
||||
let exchange = layer.definition.referenceParent.parentNode.referenceParent.parentNode.parentNode
|
||||
let plotterModule = layer.definition.referenceParent.referenceParent.referenceParent
|
||||
let session
|
||||
|
||||
if (layer.definition.referenceParent.parentNode.parentNode !== undefined) {
|
||||
if (layer.definition.referenceParent.parentNode.parentNode.type === 'Session Reference') {
|
||||
if (layer.definition.referenceParent.parentNode.parentNode.referenceParent !== undefined) {
|
||||
session = layer.definition.referenceParent.parentNode.parentNode.referenceParent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
storage.initialize(
|
||||
dataMine,
|
||||
bot,
|
||||
session,
|
||||
product,
|
||||
exchange,
|
||||
market,
|
||||
datetime,
|
||||
timeFrame,
|
||||
onProductStorageInitialized
|
||||
)
|
||||
|
||||
function onProductStorageInitialized (err) {
|
||||
try {
|
||||
switch (err.result) {
|
||||
case GLOBAL.DEFAULT_OK_RESPONSE.result: {
|
||||
break
|
||||
if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
/* 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) {
|
||||
plotter = newPlotter()
|
||||
} else {
|
||||
plotter = getNewPlotter(dataMine.code.codeName, plotterModule.parentNode.code.codeName, plotterModule.code.codeName)
|
||||
}
|
||||
case GLOBAL.DEFAULT_FAIL_RESPONSE.result: {
|
||||
callBack(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
return
|
||||
}
|
||||
default: {
|
||||
callBack(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
return
|
||||
}
|
||||
}
|
||||
/* Now we have all the initial data loaded and ready to be delivered to the new instance of the plotter. */
|
||||
let plotter
|
||||
let productDefinition
|
||||
|
||||
if (pProductCard.product.plotter.legacy === false) {
|
||||
plotter = newPlotter()
|
||||
plotter.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true)
|
||||
plotter.container.frame.position.x = thisObject.container.frame.width / 2 - plotter.container.frame.width / 2
|
||||
plotter.container.frame.position.y = thisObject.container.frame.height / 2 - plotter.container.frame.height / 2
|
||||
plotter.fitFunction = thisObject.fitFunction
|
||||
plotter.initialize(storage, datetime, timeFrame, coordinateSystem, onPlotterInizialized, product)
|
||||
|
||||
/* We take a snapwhot of the current product definition to be used by the plotter. */
|
||||
let functionLibraryProtocolNode = newProtocolNode()
|
||||
productDefinition = functionLibraryProtocolNode.getProtocolNode(pProductCard.product.node, false, true, true, false, false, true)
|
||||
} else {
|
||||
plotter = getNewPlotter(pProductCard.product.plotter.devTeam, pProductCard.product.plotter.codeName, pProductCard.product.plotter.moduleName)
|
||||
}
|
||||
|
||||
plotter.container.connectToParent(thisObject.container, true, true, false, true, true, true)
|
||||
plotter.container.frame.position.x = thisObject.container.frame.width / 2 - plotter.container.frame.width / 2
|
||||
plotter.container.frame.position.y = thisObject.container.frame.height / 2 - plotter.container.frame.height / 2
|
||||
plotter.fitFunction = thisObject.fitFunction
|
||||
plotter.initialize(storage, exchange, market, datetime, timePeriod, onPlotterInizialized, productDefinition)
|
||||
|
||||
function onPlotterInizialized () {
|
||||
try {
|
||||
let productPlotter = {
|
||||
productCard: pProductCard,
|
||||
plotter: plotter,
|
||||
storage: storage,
|
||||
profile: undefined,
|
||||
notes: undefined
|
||||
}
|
||||
/* Let the Plotter listen to the event of Cursor Files loaded, so that it can react recalculating if needed. */
|
||||
storage.eventHandler.listenToEvent('Daily File Loaded', plotter.onDailyFileLoaded)
|
||||
/* Lets load now this plotter panels. */
|
||||
productPlotter.panels = []
|
||||
|
||||
/* Here is where we instantiate the legacy panels */
|
||||
for (let i = 0; i < pProductCard.product.plotter.module.panels.length; i++) {
|
||||
let panelConfig = pProductCard.product.plotter.module.panels[i]
|
||||
|
||||
let parameters = {
|
||||
devTeam: pProductCard.product.plotter.devTeam,
|
||||
plotterCodeName: pProductCard.product.plotter.codeName,
|
||||
moduleCodeName: pProductCard.product.plotter.moduleName,
|
||||
panelCodeName: panelConfig.codeName
|
||||
function onPlotterInizialized () {
|
||||
try {
|
||||
let connector = {
|
||||
layer: layer,
|
||||
plotter: plotter,
|
||||
storage: storage
|
||||
}
|
||||
let panelOwner = exchange + ' ' + market.assetB + '/' + market.assetA
|
||||
let plotterPanelHandle = canvas.panelsSpace.createNewPanel('Plotter Panel', parameters, panelOwner, pProductCard.session)
|
||||
let plotterPanel = canvas.panelsSpace.getPanel(plotterPanelHandle, panelOwner)
|
||||
/* Connect Panel to the Plotter via an Event. */
|
||||
if (panelConfig.event !== undefined) {
|
||||
productPlotter.plotter.container.eventHandler.listenToEvent(panelConfig.event, plotterPanel.onEventRaised)
|
||||
}
|
||||
productPlotter.panels.push(plotterPanelHandle)
|
||||
}
|
||||
/* Let the Plotter listen to the event of Cursor Files loaded, so that it can react recalculating if needed. */
|
||||
plotter.onDailyFileLoadedPlotterEventsSubscriptionId = storage.eventHandler.listenToEvent('Daily File Loaded', plotter.onDailyFileLoaded)
|
||||
/* Lets load now this plotter panels. */
|
||||
connector.panels = []
|
||||
|
||||
/* Here we instantiate the UI Defined Panels. */
|
||||
if (productDefinition !== undefined) {
|
||||
for (let i = 0; i < productDefinition.referenceParent.panels.length; i++) {
|
||||
let panel = productDefinition.referenceParent.panels[i]
|
||||
if (product !== undefined) {
|
||||
for (let i = 0; i < plotterModule.panels.length; i++) {
|
||||
let panel = plotterModule.panels[i]
|
||||
|
||||
let parameters = {
|
||||
devTeam: pProductCard.product.plotter.devTeam,
|
||||
plotterCodeName: pProductCard.product.plotter.codeName,
|
||||
moduleCodeName: pProductCard.product.plotter.moduleName,
|
||||
panelCodeName: panel.id
|
||||
let parameters = {
|
||||
dataMine: dataMine.code.codeName,
|
||||
plotterCodeName: plotterModule.parentNode.code.codeName,
|
||||
moduleCodeName: plotterModule.code.codeName,
|
||||
panelNode: panel
|
||||
}
|
||||
|
||||
let owner = thisObject.payload.node.payload.parentNode.id // Panels are owned by the time machine.
|
||||
let plotterPanelHandle = canvas.panelsSpace.createNewPanel('Plotter Panel', parameters, owner, layer.session)
|
||||
let plotterPanel = canvas.panelsSpace.getPanel(plotterPanelHandle)
|
||||
|
||||
/* Connect Panel to the Plotter via an Event. */
|
||||
connector.plotter.onRecordChangeEventsSubscriptionId = connector.plotter.container.eventHandler.listenToEvent('Current Record Changed', plotterPanel.onRecordChange)
|
||||
connector.panels.push(plotterPanelHandle)
|
||||
}
|
||||
let panelOwner = exchange + ' ' + market.assetB + '/' + market.assetA
|
||||
let plotterPanelHandle = canvas.panelsSpace.createNewPanel('Plotter Panel', parameters, panelOwner, pProductCard.session, panel)
|
||||
let plotterPanel = canvas.panelsSpace.getPanel(plotterPanelHandle, panelOwner)
|
||||
|
||||
/* Connect Panel to the Plotter via an Event. */
|
||||
productPlotter.plotter.container.eventHandler.listenToEvent('Current Record Changed', plotterPanel.onRecordChange)
|
||||
productPlotter.panels.push(plotterPanelHandle)
|
||||
connector.layer.panels = connector.panels
|
||||
}
|
||||
}
|
||||
|
||||
productPlotters.push(productPlotter)
|
||||
callBack(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initializeProductPlotter -> onProductStorageInitialized -> onPlotterInizialized -> err = ' + err.stack) }
|
||||
callBack(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
thisObject.connectors.push(connector)
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initializePlotter -> onProductStorageInitialized -> onPlotterInizialized -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initializeProductPlotter -> onProductStorageInitialized -> err = ' + err.stack) }
|
||||
callBack(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initializePlotter -> onProductStorageInitialized -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initializeProductPlotter -> err = ' + err.stack) }
|
||||
callBack(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initializePlotter -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
function onProductCardStatusChanged (pProductCard) {
|
||||
if (pProductCard.status === PRODUCT_CARD_STATUS.LOADING) {
|
||||
function onLayerStatusChanged (layer) {
|
||||
if (layer.status === LAYER_STATUS.LOADING) {
|
||||
/* Lets see if we can find the Plotter of this card on our Active Plotters list, other wise we will initialize it */
|
||||
let found = false
|
||||
for (let i = 0; i < productPlotters.length; i++) {
|
||||
if (productPlotters[i].productCard.code === pProductCard.code) {
|
||||
for (let i = 0; i < thisObject.connectors.length; i++) {
|
||||
let connector = thisObject.connectors[i]
|
||||
if (connector.layer.payload.node.id === layer.payload.node.id) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if (found === false) {
|
||||
initializeProductPlotter(pProductCard, onProductPlotterInitialized)
|
||||
initializePlotter(layer, onProductPlotterInitialized)
|
||||
function onProductPlotterInitialized (err) {
|
||||
/* There is no policy yet of what to do if this fails. */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pProductCard.status === PRODUCT_CARD_STATUS.OFF) {
|
||||
if (layer.status === LAYER_STATUS.OFF) {
|
||||
/* If the plotter of this card is not on our Active Plotters list, then we remove it. */
|
||||
for (let i = 0; i < productPlotters.length; i++) {
|
||||
if (productPlotters[i].productCard.code === pProductCard.code) {
|
||||
for (let i = 0; i < thisObject.connectors.length; i++) {
|
||||
let connector = thisObject.connectors[i]
|
||||
if (connector.layer.payload.node.id === layer.payload.node.id) {
|
||||
/* Then the panels. */
|
||||
for (let j = 0; j < productPlotters[i].panels.length; j++) {
|
||||
canvas.panelsSpace.destroyPanel(productPlotters[i].panels[j])
|
||||
for (let j = 0; j < connector.panels.length; j++) {
|
||||
canvas.panelsSpace.destroyPanel(connector.panels[j])
|
||||
}
|
||||
/* Finally the Storage Objects */
|
||||
|
||||
if (productPlotters[i].plotter.finalize !== undefined) {
|
||||
productPlotters[i].plotter.container.finalize()
|
||||
productPlotters[i].plotter.finalize()
|
||||
if (connector.plotter.finalize !== undefined) {
|
||||
connector.plotter.container.eventHandler.stopListening(connector.plotter.onRecordChangeEventsSubscriptionId)
|
||||
connector.plotter.container.finalize()
|
||||
connector.plotter.finalize()
|
||||
}
|
||||
productPlotters[i].storage.finalize()
|
||||
productPlotters.splice(i, 1) // Delete item from array.
|
||||
finalizeStorage(connector.storage)
|
||||
thisObject.connectors.splice(i, 1) // Delete item from array.
|
||||
return // We already found the product woth changes and processed it.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setTimePeriod (pTimePeriod) {
|
||||
timePeriod = pTimePeriod
|
||||
if (initializationReady === true) {
|
||||
for (let i = 0; i < productPlotters.length; i++) {
|
||||
let productPlotter = productPlotters[i]
|
||||
productPlotter.productCard.setTimePeriod(timePeriod)
|
||||
productPlotter.storage.setTimePeriod(timePeriod)
|
||||
productPlotter.plotter.setTimePeriod(timePeriod)
|
||||
}
|
||||
function setTimeFrame (pTimeFrame) {
|
||||
timeFrame = pTimeFrame
|
||||
for (let i = 0; i < thisObject.connectors.length; i++) {
|
||||
let connector = thisObject.connectors[i]
|
||||
connector.layer.setTimeFrame(timeFrame)
|
||||
connector.storage.setTimeFrame(timeFrame)
|
||||
connector.plotter.setTimeFrame(timeFrame)
|
||||
}
|
||||
}
|
||||
|
||||
function setDatetime (pDatetime) {
|
||||
datetime = pDatetime
|
||||
for (let i = 0; i < productPlotters.length; i++) {
|
||||
let productPlotter = productPlotters[i]
|
||||
productPlotter.productCard.setDatetime(pDatetime)
|
||||
productPlotter.storage.setDatetime(pDatetime)
|
||||
productPlotter.plotter.setDatetime(pDatetime)
|
||||
for (let i = 0; i < thisObject.connectors.length; i++) {
|
||||
let connector = thisObject.connectors[i]
|
||||
connector.layer.setDatetime(pDatetime)
|
||||
connector.storage.setDatetime(pDatetime)
|
||||
connector.plotter.setDatetime(pDatetime)
|
||||
}
|
||||
}
|
||||
|
||||
function positionAtDatetime (pDatetime) {
|
||||
for (let i = 0; i < productPlotters.length; i++) {
|
||||
let productPlotter = productPlotters[i]
|
||||
if (productPlotter.plotter.positionAtDatetime !== undefined) {
|
||||
productPlotter.plotter.positionAtDatetime(pDatetime)
|
||||
}
|
||||
function setCoordinateSystem (pCoordinateSystem) {
|
||||
coordinateSystem = pCoordinateSystem
|
||||
for (let i = 0; i < thisObject.connectors.length; i++) {
|
||||
let connector = thisObject.connectors[i]
|
||||
connector.plotter.setCoordinateSystem(coordinateSystem)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,11 +299,11 @@ function newPlottersManager () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (productPlotters === undefined) { return } // We need to wait
|
||||
if (thisObject.connectors === undefined) { return } // We need to wait
|
||||
/* First the Product Plotters. */
|
||||
for (let i = 0; i < productPlotters.length; i++) {
|
||||
let productPlotter = productPlotters[i]
|
||||
productPlotter.plotter.draw()
|
||||
for (let i = 0; i < thisObject.connectors.length; i++) {
|
||||
let connector = thisObject.connectors[thisObject.connectors.length - i - 1]
|
||||
connector.plotter.draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
+455
-246
@@ -4,8 +4,8 @@ Markets are a function of time. When watching them, end users must be positioned
|
||||
to position themselves at any time they like.
|
||||
|
||||
In the future, it will be usefull to explore markets and compare them at different times simultaneously. Anticipating that future this module exists.
|
||||
All the charts that depand on a datetime are children of this object Time Machine. In the future we will allow users to have more than one Time Machine,
|
||||
each one with it own charts, and each one positioned at an especific point in titme.
|
||||
All the timelineCharts that depand on a datetime are children of this object Time Machine. In the future we will allow users to have more than one Time Machine,
|
||||
each one with it own timelineCharts, and each one positioned at an especific point in titme.
|
||||
|
||||
*/
|
||||
|
||||
@@ -14,25 +14,25 @@ function newTimeMachine () {
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let timeFrame = INITIAL_TIME_PERIOD
|
||||
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
timeScale: undefined,
|
||||
rateScale: undefined,
|
||||
fitFunction: undefined,
|
||||
charts: [],
|
||||
payload: undefined,
|
||||
timelineCharts: [],
|
||||
fitFunction: fitFunction,
|
||||
physics: physics,
|
||||
drawBackground: drawBackground,
|
||||
draw: draw,
|
||||
drawBackground: drawBackground,
|
||||
drawForeground: drawForeground,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let controlPanelHandle // We need this to destroy the Panel when this object is itself destroyed or no longer needs it...
|
||||
// ... also to request a reference to the object for the cases we need it.
|
||||
const SEPARATION_BETWEEN_TIMELINE_CHARTS = 1.5
|
||||
|
||||
let timeLineCoordinateSystem = newTimeLineCoordinateSystem()
|
||||
let timeMachineCoordinateSystem = newCoordinateSystem()
|
||||
|
||||
let mouse = {
|
||||
position: {
|
||||
@@ -41,188 +41,235 @@ function newTimeMachine () {
|
||||
}
|
||||
}
|
||||
|
||||
let drawScales = false
|
||||
let syncWithDesignerLoop = 0
|
||||
let timelineChartsMap = new Map()
|
||||
|
||||
let onViewportPositionChangedEventSuscriptionId
|
||||
let onViewportZoomChangedEventSuscriptionId
|
||||
let onMouseOverEventSuscriptionId
|
||||
let onMouseNotOverEventSuscriptionId
|
||||
let timeScaleValueEventSuscriptionId
|
||||
let timeScaleMouseOverEventSuscriptionId
|
||||
let rateScaleValueEventSuscriptionId
|
||||
let rateScaleMouseOverEventSuscriptionId
|
||||
let timeFrameScaleEventSuscriptionId
|
||||
let timeFrameScaleMouseOverEventSuscriptionId
|
||||
|
||||
setupContainer()
|
||||
return thisObject
|
||||
|
||||
function setupContainer () {
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME)
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.fitFunction = thisObject.fitFunction
|
||||
thisObject.container.isDraggeable = true
|
||||
thisObject.container.insideViewport = true
|
||||
thisObject.container.detectMouseOver = true
|
||||
|
||||
thisObject.container.frame.width = TIME_MACHINE_WIDTH
|
||||
thisObject.container.frame.height = TIME_MACHINE_HEIGHT
|
||||
|
||||
thisObject.container.frame.position.x = browserCanvas.width / 2 - TIME_MACHINE_WIDTH / 2
|
||||
thisObject.container.frame.position.y = browserCanvas.height / 2 - TIME_MACHINE_HEIGHT / 2
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
for (let i = 0; i < thisObject.charts.length; i++) {
|
||||
let chart = thisObject.charts[i]
|
||||
chart.finalize()
|
||||
}
|
||||
|
||||
thisObject.charts = []
|
||||
canvas.chartSpace.viewport.eventHandler.stopListening(onViewportPositionChangedEventSuscriptionId)
|
||||
canvas.chartSpace.viewport.eventHandler.stopListening(onViewportZoomChangedEventSuscriptionId)
|
||||
|
||||
if (thisObject.timeScale !== undefined) {
|
||||
thisObject.timeScale.finalize()
|
||||
thisObject.timeScale = undefined
|
||||
finalizeTimeScale()
|
||||
}
|
||||
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
thisObject.rateScale.finalize()
|
||||
thisObject.rateScale = undefined
|
||||
finalizeRateScale()
|
||||
}
|
||||
|
||||
thisObject.fitFunction = undefined
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
finalizeTimeFrameScale()
|
||||
}
|
||||
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSuscriptionId)
|
||||
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[i]
|
||||
timelineChart.container.eventHandler.stopListening(timelineChart.onChildrenMouseOverEventSuscriptionId)
|
||||
timelineChart.finalize()
|
||||
}
|
||||
|
||||
thisObject.timelineCharts = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
setupContainer()
|
||||
thisObject.payload = undefined
|
||||
|
||||
mouse = undefined
|
||||
timelineChartsMap = undefined
|
||||
|
||||
timeMachineCoordinateSystem.finalize()
|
||||
timeMachineCoordinateSystem = undefined
|
||||
}
|
||||
|
||||
function finalizeTimeScale () {
|
||||
if (thisObject.timeScale === undefined) { return }
|
||||
|
||||
thisObject.timeScale.container.eventHandler.stopListening(timeScaleValueEventSuscriptionId)
|
||||
thisObject.timeScale.container.eventHandler.stopListening(timeScaleMouseOverEventSuscriptionId)
|
||||
thisObject.timeScale.finalize()
|
||||
thisObject.timeScale = undefined
|
||||
}
|
||||
|
||||
function finalizeRateScale () {
|
||||
if (thisObject.rateScale === undefined) { return }
|
||||
|
||||
thisObject.rateScale.container.eventHandler.stopListening(rateScaleValueEventSuscriptionId)
|
||||
thisObject.rateScale.container.eventHandler.stopListening(rateScaleMouseOverEventSuscriptionId)
|
||||
thisObject.rateScale.finalize()
|
||||
thisObject.rateScale = undefined
|
||||
}
|
||||
|
||||
function finalizeTimeFrameScale () {
|
||||
if (thisObject.timeFrameScale === undefined) { return }
|
||||
|
||||
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleEventSuscriptionId)
|
||||
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleMouseOverEventSuscriptionId)
|
||||
thisObject.timeFrameScale.finalize()
|
||||
thisObject.timeFrameScale = undefined
|
||||
}
|
||||
|
||||
function initialize (callBackFunction) {
|
||||
/* Each Time Machine has a Control Panel. */
|
||||
timeFrame = INITIAL_TIME_PERIOD
|
||||
loadFrame(thisObject.payload, thisObject.container.frame)
|
||||
|
||||
let panelOwner = 'Global'
|
||||
controlPanelHandle = canvas.panelsSpace.createNewPanel('Time Control Panel', undefined, panelOwner)
|
||||
let controlPanel = canvas.panelsSpace.getPanel(controlPanelHandle, panelOwner)
|
||||
recalculateCoordinateSystem()
|
||||
recalculateCurrentDatetime()
|
||||
|
||||
recalculateScale()
|
||||
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseNotOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
|
||||
/* First, we initialize the market that we are going to show first on screen. Later all the other markets will be initialized on the background. */
|
||||
onViewportPositionChangedEventSuscriptionId = canvas.chartSpace.viewport.eventHandler.listenToEvent('Position Changed', onViewportPositionChanged)
|
||||
onViewportZoomChangedEventSuscriptionId = canvas.chartSpace.viewport.eventHandler.listenToEvent('Zoom Changed', onViewportZoomChanged)
|
||||
|
||||
let position = 0 // This defines the position of each chart respect to each other.
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
}
|
||||
|
||||
let timelineChart = newTimelineChart()
|
||||
function onMouseOver (event) {
|
||||
drawScales = true
|
||||
|
||||
timelineChart.container.connectToParent(thisObject.container, true, true, false, true, true, true)
|
||||
timelineChart.container.frame.height = thisObject.container.frame.height
|
||||
mouse.position.x = event.x
|
||||
mouse.position.y = event.y
|
||||
|
||||
timelineChart.container.frame.position.x = thisObject.container.frame.width / 2 - timelineChart.container.frame.width / 2
|
||||
timelineChart.container.frame.position.y = timelineChart.container.frame.height * SEPARATION_BETWEEN_TIMELINE_CHARTS * position
|
||||
|
||||
position++
|
||||
|
||||
timelineChart.initialize(DEFAULT_EXCHANGE, DEFAULT_MARKET, timeLineCoordinateSystem, onDefaultInitialized)
|
||||
|
||||
function onDefaultInitialized (err) {
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
callBackFunction(err)
|
||||
return
|
||||
}
|
||||
|
||||
thisObject.charts.push(timelineChart)
|
||||
|
||||
controlPanel.container.eventHandler.listenToEvent('Datetime Changed', timelineChart.setDatetime, undefined)
|
||||
timelineChart.container.eventHandler.listenToEvent('Datetime Changed', controlPanel.setDatetime)
|
||||
|
||||
/* Each Time Machine has a Time Scale and a Right Scale. */
|
||||
|
||||
thisObject.timeScale = newTimeScale()
|
||||
thisObject.timeScale.fitFunction = thisObject.fitFunction
|
||||
|
||||
thisObject.timeScale.container.eventHandler.listenToEvent('Lenght Percentage Changed', function (event) {
|
||||
thisObject.container.frame.width = TIME_MACHINE_WIDTH * event.lenghtPercentage / 100
|
||||
recalculateScale()
|
||||
moveToUserPosition(thisObject.container, timeLineCoordinateSystem, false, true, event.mousePosition)
|
||||
thisObject.container.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
})
|
||||
|
||||
thisObject.timeScale.initialize()
|
||||
|
||||
thisObject.rateScale = newRateScale()
|
||||
thisObject.rateScale.fitFunction = thisObject.fitFunction
|
||||
|
||||
thisObject.rateScale.container.eventHandler.listenToEvent('Height Percentage Changed', function (event) {
|
||||
thisObject.container.frame.height = TIME_MACHINE_HEIGHT * event.heightPercentage / 100
|
||||
recalculateScale()
|
||||
moveToUserPosition(thisObject.container, timeLineCoordinateSystem, true, false, event.mousePosition)
|
||||
thisObject.container.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
})
|
||||
|
||||
thisObject.rateScale.initialize()
|
||||
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
|
||||
initializeTheRest()
|
||||
if (thisObject.timeScale !== undefined) {
|
||||
thisObject.timeScale.onMouseOverSomeTimeMachineContainer(event)
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
thisObject.timeScale.visible = true
|
||||
thisObject.rateScale.visible = true
|
||||
|
||||
mouse.position.x = event.x
|
||||
mouse.position.y = event.y
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
thisObject.rateScale.onMouseOverSomeTimeMachineContainer(event)
|
||||
}
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
thisObject.timeFrameScale.onMouseOverSomeTimeMachineContainer(event)
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTheRest () {
|
||||
let leftToInitialize = SUPPORTED_EXCHANGES.length * SUPPORTED_MARKETS.length - 1 // The default exchange and market was already initialized.
|
||||
let alreadyInitialized = 0
|
||||
function onMouseNotOver (event) {
|
||||
drawScales = false
|
||||
|
||||
if (alreadyInitialized === leftToInitialize) {
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
return
|
||||
if (thisObject.timeScale !== undefined) {
|
||||
thisObject.timeScale.visible = false
|
||||
}
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
thisObject.rateScale.visible = false
|
||||
}
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
thisObject.timeFrameScale.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTimeScale () {
|
||||
thisObject.timeScale = newTimeScale()
|
||||
thisObject.timeScale.fitFunction = thisObject.fitFunction
|
||||
thisObject.timeScale.payload = thisObject.payload.node.timeScale.payload
|
||||
|
||||
timeScaleValueEventSuscriptionId = thisObject.timeScale.container.eventHandler.listenToEvent('Time Scale Value Changed', timeScaleValueChanged)
|
||||
timeScaleMouseOverEventSuscriptionId = thisObject.timeScale.container.eventHandler.listenToEvent('onMouseOverScale', timeScaleMouseOver)
|
||||
thisObject.timeScale.initialize(timeMachineCoordinateSystem, thisObject.container)
|
||||
|
||||
function timeScaleValueChanged (event) {
|
||||
if (event.isUserAction === true) {
|
||||
let currentDate = getDateFromPoint(event.mousePosition, thisObject.container, timeMachineCoordinateSystem)
|
||||
let currentRate = getRateFromPoint(event.mousePosition, thisObject.container, timeMachineCoordinateSystem)
|
||||
thisObject.container.frame.width = TIME_MACHINE_WIDTH + TIME_MACHINE_WIDTH * event.scale
|
||||
recalculateCoordinateSystem()
|
||||
moveToUserPosition(thisObject.container, currentDate, currentRate, timeMachineCoordinateSystem, false, true, event.mousePosition)
|
||||
} else {
|
||||
thisObject.container.frame.width = TIME_MACHINE_WIDTH + TIME_MACHINE_WIDTH * event.scale
|
||||
recalculateCoordinateSystem()
|
||||
}
|
||||
thisObject.container.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
}
|
||||
function timeScaleMouseOver (event) {
|
||||
thisObject.container.eventHandler.raiseEvent('onMouseOver', event)
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < SUPPORTED_EXCHANGES.length; i++) {
|
||||
for (let j = 0; j < SUPPORTED_MARKETS.length; j++) {
|
||||
let exchange = SUPPORTED_EXCHANGES[i]
|
||||
let market = SUPPORTED_MARKETS[j]
|
||||
function initializeRateScale () {
|
||||
thisObject.rateScale = newRateScale()
|
||||
thisObject.rateScale.fitFunction = thisObject.fitFunction
|
||||
thisObject.rateScale.payload = thisObject.payload.node.rateScale.payload
|
||||
|
||||
if (
|
||||
exchange === DEFAULT_EXCHANGE &&
|
||||
market.assetA === DEFAULT_MARKET.assetA &&
|
||||
market.assetB === DEFAULT_MARKET.assetB
|
||||
) { continue }
|
||||
rateScaleValueEventSuscriptionId = thisObject.rateScale.container.eventHandler.listenToEvent('Rate Scale Value Changed', rateScaleValueChanged)
|
||||
rateScaleMouseOverEventSuscriptionId = thisObject.rateScale.container.eventHandler.listenToEvent('onMouseOverScale', rateScaleMouseOver)
|
||||
thisObject.rateScale.initialize(timeMachineCoordinateSystem, thisObject.container, thisObject.container)
|
||||
|
||||
initializeTimelineChart(exchange, market)
|
||||
}
|
||||
function rateScaleValueChanged (event) {
|
||||
if (event.isUserAction === true) {
|
||||
let currentDate = getDateFromPoint(event.mousePosition, thisObject.container, timeMachineCoordinateSystem)
|
||||
let currentRate = getRateFromPoint(event.mousePosition, thisObject.container, timeMachineCoordinateSystem)
|
||||
|
||||
thisObject.container.frame.height = TIME_MACHINE_HEIGHT + TIME_MACHINE_HEIGHT * event.scale
|
||||
recalculateCoordinateSystem()
|
||||
moveToUserPosition(thisObject.container, currentDate, currentRate, timeMachineCoordinateSystem, true, false, event.mousePosition)
|
||||
} else {
|
||||
thisObject.container.frame.height = TIME_MACHINE_HEIGHT + TIME_MACHINE_HEIGHT * event.scale
|
||||
recalculateCoordinateSystem()
|
||||
}
|
||||
thisObject.container.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
thisObject.container.eventHandler.raiseEvent('Upstream Rate Scale Value Changed', event)
|
||||
}
|
||||
function rateScaleMouseOver (event) {
|
||||
thisObject.container.eventHandler.raiseEvent('onMouseOver', event)
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTimelineChart (exchange, market) {
|
||||
let timelineChart = newTimelineChart()
|
||||
function initializeTimeFrameScale () {
|
||||
thisObject.timeFrameScale = newTimeFrameScale()
|
||||
thisObject.timeFrameScale.fitFunction = thisObject.fitFunction
|
||||
thisObject.timeFrameScale.payload = thisObject.payload.node.timeFrameScale.payload
|
||||
|
||||
timelineChart.container.connectToParent(thisObject.container, true, true, false, true, true, true)
|
||||
timeFrameScaleEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('Time Frame Value Changed', timeFrameScaleValueChanged)
|
||||
timeFrameScaleMouseOverEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('onMouseOverScale', timeFrameScaleMouseOver)
|
||||
thisObject.timeFrameScale.initialize(thisObject.container)
|
||||
|
||||
timelineChart.container.frame.height = thisObject.container.frame.height
|
||||
|
||||
timelineChart.container.frame.position.x = thisObject.container.frame.width / 2 - timelineChart.container.frame.width / 2
|
||||
timelineChart.container.frame.position.y = timelineChart.container.frame.height * SEPARATION_BETWEEN_TIMELINE_CHARTS * position
|
||||
|
||||
position++
|
||||
|
||||
timelineChart.initialize(exchange, market, timeLineCoordinateSystem, finalSteps)
|
||||
|
||||
function finalSteps () {
|
||||
thisObject.charts.push(timelineChart)
|
||||
|
||||
controlPanel.container.eventHandler.listenToEvent('Datetime Changed', timelineChart.setDatetime, undefined)
|
||||
timelineChart.container.eventHandler.listenToEvent('Datetime Changed', controlPanel.setDatetime)
|
||||
|
||||
alreadyInitialized++
|
||||
|
||||
if (alreadyInitialized === leftToInitialize) {
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
function timeFrameScaleValueChanged (event) {
|
||||
let currentTimeFrame = timeFrame
|
||||
timeFrame = event.timeFrame
|
||||
if (timeFrame !== currentTimeFrame) {
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[i]
|
||||
timelineChart.upstreamTimeFrame = timeFrame
|
||||
if (timelineChart.timeFrameScale === undefined) {
|
||||
timelineChart.setTimeFrame(timeFrame)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function timeFrameScaleMouseOver (event) {
|
||||
thisObject.container.eventHandler.raiseEvent('onMouseOver', event)
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point, purpose) {
|
||||
let container
|
||||
|
||||
if (thisObject.timeScale !== undefined) {
|
||||
container = thisObject.timeScale.getContainer(point)
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) {
|
||||
container = thisObject.rateScale.getContainer(point)
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
@@ -231,8 +278,26 @@ function newTimeMachine () {
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.charts.length; i++) {
|
||||
container = this.charts[i].getContainer(point)
|
||||
if (thisObject.timeScale !== undefined && thisObject.timeScale.isVisible === true) {
|
||||
container = thisObject.timeScale.getContainer(point)
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) {
|
||||
container = thisObject.timeFrameScale.getContainer(point)
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
container = thisObject.timelineCharts[i].getContainer(point, purpose)
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
if (thisObject.container.frame.isThisPointHere(point) === true) {
|
||||
@@ -244,143 +309,277 @@ function newTimeMachine () {
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point) === true) {
|
||||
return thisObject.container
|
||||
} else {
|
||||
if (purpose === GET_CONTAINER_PURPOSE.MOUSE_OVER) {
|
||||
thisObject.container.eventHandler.raiseEvent('onMouseNotOver')
|
||||
if (thisObject.timeScale !== undefined) {
|
||||
thisObject.timeScale.visible = false
|
||||
}
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
thisObject.rateScale.visible = false
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function onViewportZoomChanged (event) {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
recalculateCurrentDatetime()
|
||||
}
|
||||
}
|
||||
|
||||
function onViewportPositionChanged () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
recalculateCurrentDatetime()
|
||||
}
|
||||
}
|
||||
|
||||
function recalculateCurrentDatetime () {
|
||||
/*
|
||||
The view port was moved or the view port zoom level was changed and the center of the screen points to a different datetime that we
|
||||
must calculate.
|
||||
*/
|
||||
let center = {
|
||||
x: (canvas.chartSpace.viewport.visibleArea.bottomRight.x - canvas.chartSpace.viewport.visibleArea.bottomLeft.x) / 2,
|
||||
y: (canvas.chartSpace.viewport.visibleArea.bottomRight.y - canvas.chartSpace.viewport.visibleArea.topRight.y) / 2
|
||||
}
|
||||
|
||||
center = unTransformThisPoint(center, thisObject.container)
|
||||
center = timeMachineCoordinateSystem.unInverseTransform(center, thisObject.container.frame.height)
|
||||
|
||||
datetime = new Date(center.x)
|
||||
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[i]
|
||||
timelineChart.setDatetime(datetime)
|
||||
}
|
||||
}
|
||||
|
||||
function fitFunction (point, fullVisible, margin, topMargin, bottomMargin) {
|
||||
/* We prevent a point to be out of the container AND out of the Chart Space in general */
|
||||
|
||||
let returnPoint = {
|
||||
x: point.x,
|
||||
y: point.y
|
||||
}
|
||||
|
||||
let upCorner = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let bottonCorner = {
|
||||
x: thisObject.container.frame.width,
|
||||
y: thisObject.container.frame.height
|
||||
}
|
||||
|
||||
upCorner = transformThisPoint(upCorner, thisObject.container)
|
||||
bottonCorner = transformThisPoint(bottonCorner, thisObject.container)
|
||||
|
||||
/* Checking against the container limits. */
|
||||
if (margin === undefined) { margin = 0 }
|
||||
if (topMargin === undefined) { topMargin = 0 }
|
||||
if (bottomMargin === undefined) { bottomMargin = 0 }
|
||||
|
||||
if (returnPoint.x - margin < upCorner.x) { returnPoint.x = upCorner.x + margin }
|
||||
if (returnPoint.x + margin > bottonCorner.x) { returnPoint.x = bottonCorner.x - margin }
|
||||
if (returnPoint.y - margin - topMargin < upCorner.y) { returnPoint.y = upCorner.y + margin + topMargin }
|
||||
if (returnPoint.y + margin + bottomMargin > bottonCorner.y) { returnPoint.y = bottonCorner.y - margin - bottomMargin }
|
||||
|
||||
returnPoint = canvas.chartSpace.fitFunction(returnPoint, fullVisible)
|
||||
|
||||
return returnPoint
|
||||
}
|
||||
|
||||
function physics () {
|
||||
thisObjectPhysics()
|
||||
childrenPhysics()
|
||||
saveFrame(thisObject.payload, thisObject.container.frame)
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
childrenPhysics()
|
||||
syncWithDesigner()
|
||||
}
|
||||
panelPhysics()
|
||||
}
|
||||
|
||||
function thisObjectPhysics () {
|
||||
/* Screen Corner Date Calculation */
|
||||
function panelPhysics () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
canvas.panelsSpace.makeVisible(thisObject.payload.node.id, 'Layers Panel')
|
||||
} else {
|
||||
canvas.panelsSpace.makeInvisible(thisObject.payload.node.id, 'Layers Panel')
|
||||
}
|
||||
}
|
||||
|
||||
let point = {
|
||||
x: 0,
|
||||
y: 0
|
||||
function syncWithDesigner () {
|
||||
syncWithDesignerTimelineCharts()
|
||||
syncWithDesignerScales()
|
||||
}
|
||||
|
||||
function syncWithDesignerScales () {
|
||||
if (thisObject.payload.node === undefined) {
|
||||
finalizeTimeScale()
|
||||
finalizeRateScale()
|
||||
finalizeTimeFrameScale()
|
||||
return
|
||||
}
|
||||
if (thisObject.payload.node.timeScale === undefined && thisObject.timeScale !== undefined) {
|
||||
finalizeTimeScale()
|
||||
}
|
||||
if (thisObject.payload.node.timeScale !== undefined && thisObject.timeScale === undefined) {
|
||||
initializeTimeScale()
|
||||
}
|
||||
if (thisObject.payload.node.rateScale === undefined && thisObject.rateScale !== undefined) {
|
||||
finalizeRateScale()
|
||||
}
|
||||
if (thisObject.payload.node.rateScale !== undefined && thisObject.rateScale === undefined) {
|
||||
initializeRateScale()
|
||||
}
|
||||
if (thisObject.payload.node.timeFrameScale === undefined && thisObject.timeFrameScale !== undefined) {
|
||||
finalizeTimeFrameScale()
|
||||
}
|
||||
if (thisObject.payload.node.timeFrameScale !== undefined && thisObject.timeFrameScale === undefined) {
|
||||
initializeTimeFrameScale()
|
||||
}
|
||||
}
|
||||
|
||||
function syncWithDesignerTimelineCharts () {
|
||||
syncWithDesignerLoop = syncWithDesignerLoop + 0.00000000001
|
||||
|
||||
for (let j = 0; j < thisObject.payload.node.timelineCharts.length; j++) {
|
||||
let node = thisObject.payload.node.timelineCharts[j]
|
||||
let timelineChart = timelineChartsMap.get(node.id)
|
||||
if (timelineChart === undefined) {
|
||||
/* The timeline timelineChart node is new, thus we need to initialize a new timelineChart */
|
||||
initializeTimelineChart(node, syncWithDesignerLoop)
|
||||
} else {
|
||||
/* The time machine already exists, we tag it as existing at the current loop. */
|
||||
timelineChart.syncWithDesignerLoop = syncWithDesignerLoop
|
||||
}
|
||||
}
|
||||
|
||||
let cornerDate = getDateFromPoint(point, thisObject.container, timeLineCoordinateSystem)
|
||||
cornerDate = new Date(cornerDate)
|
||||
window.localStorage.setItem('Date @ Screen Corner', cornerDate.toUTCString())
|
||||
/* We check all the timeMachines we have to see if we need to remove any of them */
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[i]
|
||||
if (timelineChart.syncWithDesignerLoop < syncWithDesignerLoop) {
|
||||
/* Must be removed */
|
||||
timelineChart.container.eventHandler.stopListening(timelineChart.onChildrenMouseOverEventSuscriptionId)
|
||||
timelineChart.finalize()
|
||||
timelineChartsMap.delete(timelineChart.nodeId)
|
||||
thisObject.timelineCharts.splice(i, 1)
|
||||
/* We remove one at the time */
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTimelineChart (node, syncWithDesignerLoop) {
|
||||
let timelineChart = newTimelineChart()
|
||||
timelineChart.syncWithDesignerLoop = syncWithDesignerLoop
|
||||
timelineChart.payload = node.payload
|
||||
timelineChart.nodeId = node.id
|
||||
timelineChartsMap.set(node.id, timelineChart)
|
||||
timelineChart.payload.uiObject.setValue('Loading...')
|
||||
|
||||
/* Setting up the new timeline timelineChart. */
|
||||
timelineChart.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true)
|
||||
timelineChart.container.fitFunction = thisObject.container.fitFunction
|
||||
timelineChart.fitFunction = thisObject.fitFunction
|
||||
timelineChart.container.frame.width = thisObject.container.frame.width
|
||||
timelineChart.container.frame.height = thisObject.container.frame.height
|
||||
timelineChart.container.frame.position.x = 0
|
||||
timelineChart.container.frame.position.y = 0
|
||||
timelineChart.initialize(timeMachineCoordinateSystem)
|
||||
|
||||
/* we will store the event suscription id as a property of the timelineChart, to avoid keeping it an a separate array */
|
||||
timelineChart.onChildrenMouseOverEventSuscriptionId = timelineChart.container.eventHandler.listenToEvent('onChildrenMouseOver', onChildrenMouseOver)
|
||||
|
||||
thisObject.timelineCharts.push(timelineChart)
|
||||
timelineChart.payload.uiObject.setValue('')
|
||||
|
||||
function onChildrenMouseOver (event) {
|
||||
thisObject.container.eventHandler.raiseEvent('onMouseOver', event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function childrenPhysics () {
|
||||
if (thisObject.timeScale === undefined) { return }
|
||||
if (thisObject.rateScale === undefined) { return }
|
||||
|
||||
thisObject.timeScale.physics()
|
||||
thisObject.rateScale.physics()
|
||||
|
||||
for (let i = 0; i < thisObject.charts.length; i++) {
|
||||
let chart = thisObject.charts[i]
|
||||
chart.physics()
|
||||
if (thisObject.timeScale !== undefined) {
|
||||
thisObject.timeScale.physics()
|
||||
}
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
thisObject.rateScale.physics()
|
||||
}
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
thisObject.timeFrameScale.physics()
|
||||
}
|
||||
|
||||
/* Mouse Position Date Calculation */
|
||||
|
||||
let timePoint = {
|
||||
x: mouse.position.x,
|
||||
y: 0
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[i]
|
||||
timelineChart.physics()
|
||||
}
|
||||
|
||||
let mouseDate = getDateFromPoint(timePoint, thisObject.container, timeLineCoordinateSystem)
|
||||
|
||||
thisObject.timeScale.date = new Date(mouseDate)
|
||||
|
||||
/* Mouse Position Rate Calculation */
|
||||
|
||||
let ratePoint = {
|
||||
x: 0,
|
||||
y: mouse.position.y
|
||||
}
|
||||
|
||||
let mouseRate = getRateFromPoint(ratePoint, thisObject.container, timeLineCoordinateSystem)
|
||||
|
||||
thisObject.rateScale.rate = mouseRate
|
||||
|
||||
/* timeScale Positioning */
|
||||
|
||||
thisObject.timeScale.container.frame.position.x = mouse.position.x - thisObject.timeScale.container.frame.width / 2
|
||||
|
||||
timePoint = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
timePoint = transformThisPoint(timePoint, thisObject.container.frame.container)
|
||||
timePoint = thisObject.container.fitFunction(timePoint)
|
||||
|
||||
thisObject.timeScale.container.frame.position.y = timePoint.y
|
||||
|
||||
/* rateScale Positioning */
|
||||
|
||||
thisObject.rateScale.container.frame.position.y = mouse.position.y - thisObject.rateScale.container.frame.height / 2
|
||||
|
||||
ratePoint = {
|
||||
x: 10000000000000,
|
||||
y: 0
|
||||
}
|
||||
|
||||
ratePoint = transformThisPoint(ratePoint, thisObject.container.frame.container)
|
||||
ratePoint = thisObject.container.fitFunction(ratePoint)
|
||||
|
||||
thisObject.rateScale.container.frame.position.x = ratePoint.x - thisObject.rateScale.container.frame.width
|
||||
}
|
||||
|
||||
function drawBackground () {
|
||||
thisBackground()
|
||||
|
||||
drawChartsBackground()
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
for (let i = 0; i < this.charts.length; i++) {
|
||||
let chart = this.charts[i]
|
||||
chart.drawBackground()
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[thisObject.timelineCharts.length - i - 1]
|
||||
timelineChart.drawBackground()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawChartsBackground () {
|
||||
drawContainerBackground(thisObject.container, UI_COLOR.WHITE, 0.5, thisObject.fitFunction)
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
for (let i = 0; i < this.charts.length; i++) {
|
||||
let chart = this.charts[i]
|
||||
chart.draw()
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[thisObject.timelineCharts.length - i - 1]
|
||||
timelineChart.draw()
|
||||
}
|
||||
|
||||
if (thisObject.timeScale !== undefined) { thisObject.timeScale.draw() }
|
||||
if (thisObject.rateScale !== undefined) { thisObject.rateScale.draw() }
|
||||
if (drawScales === true) {
|
||||
if (thisObject.timeScale !== undefined && thisObject.timeScale.isVisible === true) { thisObject.timeScale.draw() }
|
||||
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.draw() }
|
||||
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.draw() }
|
||||
}
|
||||
} else {
|
||||
let icon = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
let imageSize = 40
|
||||
let imagePosition = {
|
||||
x: thisObject.container.frame.width / 2,
|
||||
y: thisObject.container.frame.height / 2
|
||||
}
|
||||
|
||||
// thisObject.container.frame.draw(false, true, false)
|
||||
imagePosition = transformThisPoint(imagePosition, thisObject.container)
|
||||
imagePosition = thisObject.fitFunction(imagePosition, true)
|
||||
|
||||
browserCanvasContext.drawImage(
|
||||
icon,
|
||||
imagePosition.x - imageSize / 2,
|
||||
imagePosition.y - imageSize / 2,
|
||||
imageSize,
|
||||
imageSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function thisBackground () {
|
||||
return
|
||||
let params = {
|
||||
cornerRadius: 15,
|
||||
lineWidth: 5,
|
||||
opacity: 1,
|
||||
container: thisObject.container,
|
||||
borderColor: UI_COLOR.RUSTED_RED,
|
||||
backgroundColor: UI_COLOR.WHITE,
|
||||
fitFunction: thisObject.fitFunction,
|
||||
coordinateSystem: timeLineCoordinateSystem
|
||||
}
|
||||
function drawForeground () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
for (let i = 0; i < thisObject.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.timelineCharts[thisObject.timelineCharts.length - i - 1]
|
||||
timelineChart.drawForeground()
|
||||
}
|
||||
|
||||
roundedCornersBackground(params)
|
||||
if (drawScales === true) {
|
||||
if (thisObject.timeScale !== undefined && thisObject.timeScale.isVisible === true) { thisObject.timeScale.drawForeground() }
|
||||
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.drawForeground() }
|
||||
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawForeground() }
|
||||
}
|
||||
|
||||
let style = {
|
||||
color: UI_COLOR.BLACK,
|
||||
opacity: 1,
|
||||
lineWidth: 1,
|
||||
lineDash: [1, 3]
|
||||
}
|
||||
thisObject.container.frame.draw(false, true, false, thisObject.fitFunction, style)
|
||||
}
|
||||
}
|
||||
|
||||
function recalculateScale () {
|
||||
function recalculateCoordinateSystem () {
|
||||
let minValue = {
|
||||
x: MIN_PLOTABLE_DATE.valueOf(),
|
||||
y: 0
|
||||
@@ -388,10 +587,20 @@ function newTimeMachine () {
|
||||
|
||||
let maxValue = {
|
||||
x: MAX_PLOTABLE_DATE.valueOf(),
|
||||
y: nextPorwerOf10(USDT_BTC_HTH) / 4
|
||||
y: nextPorwerOf10(MAX_DEFAULT_RATE_SCALE_VALUE) / 4
|
||||
}
|
||||
|
||||
timeLineCoordinateSystem.initialize(
|
||||
if (thisObject.timeScale !== undefined) {
|
||||
minValue.x = thisObject.timeScale.fromDate
|
||||
maxValue.x = thisObject.timeScale.toDate
|
||||
}
|
||||
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
minValue.y = thisObject.rateScale.minValue
|
||||
maxValue.y = thisObject.rateScale.maxValue
|
||||
}
|
||||
|
||||
timeMachineCoordinateSystem.initialize(
|
||||
minValue,
|
||||
maxValue,
|
||||
thisObject.container.frame.width,
|
||||
|
||||
+323
-427
@@ -3,48 +3,57 @@ function newTimelineChart () {
|
||||
const INFO_LOG = false
|
||||
const INTENSIVE_LOG = false
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
let logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let timeLineCoordinateSystem
|
||||
|
||||
let timePeriod = INITIAL_TIME_PERIOD
|
||||
let timeFrame = INITIAL_TIME_PERIOD
|
||||
let datetime = NEW_SESSION_INITIAL_DATE
|
||||
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
fitFunction: undefined,
|
||||
physics: physics,
|
||||
rateScale: undefined,
|
||||
timeFrameScale: undefined,
|
||||
payload: undefined,
|
||||
layersManager: undefined,
|
||||
plotterManager: undefined,
|
||||
upstreamTimeFrame: undefined,
|
||||
setDatetime: setDatetime,
|
||||
drawBackground: drawBackground,
|
||||
setTimeFrame: setTimeFrame,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
drawBackground: drawBackground,
|
||||
drawForeground: drawForeground,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
thisObject.fitFunction = canvas.chartSpace.fitIntoVisibleArea
|
||||
let timeMachineCoordinateSystem
|
||||
let timelineChartCoordinateSystem = newCoordinateSystem()
|
||||
let coordinateSystem
|
||||
|
||||
let initializationReady = false
|
||||
let layersPanel
|
||||
let layersPanelHandle
|
||||
|
||||
let productsPanel
|
||||
let onMouseOverEventSuscriptionId
|
||||
let onMouseNotOverEventSuscriptionId
|
||||
let rateScaleValueEventSuscriptionId
|
||||
let rateScaleUpstreamEventSuscriptionId
|
||||
let rateScaleMouseOverEventSuscriptionId
|
||||
let rateScaleOffsetEventSuscriptionId
|
||||
let rateScaleUpstreamDimensionsEventSuscriptionId
|
||||
let timeFrameScaleEventSuscriptionId
|
||||
let timeFrameScaleMouseOverEventSuscriptionId
|
||||
let scaleChangedEventSubscriptionId
|
||||
|
||||
/* Background */
|
||||
let logoAssetA
|
||||
let logoAssetB
|
||||
let logoExchange
|
||||
let logoAA
|
||||
let canDrawLogoA = false
|
||||
let canDrawLogoB = false
|
||||
let canDrawLogoExchange = false
|
||||
let canDrawLogoAA = false
|
||||
|
||||
let plotterManager
|
||||
let exchange
|
||||
let market
|
||||
|
||||
let productsPanelHandle
|
||||
let timePeriodScale
|
||||
let drawScales = false
|
||||
let mouse = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
|
||||
setupContainer()
|
||||
return thisObject
|
||||
@@ -56,192 +65,249 @@ function newTimelineChart () {
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
plotterManager.finalize()
|
||||
plotterManager = undefined
|
||||
timePeriodScale.finalize()
|
||||
timePeriodScale = undefined
|
||||
canvas.panelsSpace.destroyPanel(productsPanelHandle)
|
||||
coordinateSystem.eventHandler.stopListening(timelineChartCoordinateSystem)
|
||||
|
||||
if (thisObject.layersManager !== undefined) {
|
||||
finalizeLayersManager()
|
||||
}
|
||||
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
finalizeRateScale()
|
||||
}
|
||||
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
finalizeTimeFrameScale()
|
||||
}
|
||||
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSuscriptionId)
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
setupContainer()
|
||||
thisObject.payload = undefined
|
||||
|
||||
mouse = undefined
|
||||
logger = undefined
|
||||
|
||||
timeMachineCoordinateSystem = undefined
|
||||
timelineChartCoordinateSystem.finalize()
|
||||
timelineChartCoordinateSystem = undefined
|
||||
coordinateSystem = undefined
|
||||
layersPanel = undefined
|
||||
layersPanelHandle = undefined
|
||||
}
|
||||
|
||||
function initialize (pExchange, pMarket, pTimeLineCoordinateSystem, callBackFunction) {
|
||||
try {
|
||||
if (INFO_LOG === true) { logger.write('[INFO] initialize -> Entering function.') }
|
||||
function finalizeLayersManager () {
|
||||
if (thisObject.plotterManager !== undefined) {
|
||||
thisObject.plotterManager.finalize()
|
||||
}
|
||||
thisObject.plotterManager = undefined
|
||||
thisObject.layersManager = undefined
|
||||
|
||||
/* We load the logow we will need for the background. */
|
||||
exchange = pExchange
|
||||
market = pMarket
|
||||
timeLineCoordinateSystem = pTimeLineCoordinateSystem
|
||||
canvas.panelsSpace.destroyPanel(layersPanelHandle)
|
||||
}
|
||||
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseOver', function (event) {
|
||||
saveUserPosition(thisObject.container, timeLineCoordinateSystem, event)
|
||||
})
|
||||
function finalizeTimeFrameScale () {
|
||||
if (thisObject.timeFrameScale === undefined) { return }
|
||||
|
||||
let panelOwner = exchange + ' ' + market.assetB + '/' + market.assetA
|
||||
productsPanelHandle = canvas.panelsSpace.createNewPanel('Products Panel', undefined, panelOwner)
|
||||
let productsPanel = canvas.panelsSpace.getPanel(productsPanelHandle, panelOwner)
|
||||
productsPanel.initialize(exchange, market)
|
||||
|
||||
logoA = new Image()
|
||||
logoB = new Image()
|
||||
logoExchange = new Image()
|
||||
logoAA = new Image()
|
||||
|
||||
logoA.onload = onImageALoaded
|
||||
|
||||
function onImageALoaded () {
|
||||
canDrawLogoA = true
|
||||
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleEventSuscriptionId)
|
||||
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleMouseOverEventSuscriptionId)
|
||||
thisObject.timeFrameScale.finalize()
|
||||
thisObject.timeFrameScale = undefined
|
||||
if (thisObject.upstreamTimeFrame !== undefined) {
|
||||
timeFrame = thisObject.upstreamTimeFrame
|
||||
if (thisObject.plotterManager !== undefined) {
|
||||
thisObject.plotterManager.setTimeFrame(timeFrame)
|
||||
}
|
||||
|
||||
logoB.onload = onImageBLoaded
|
||||
|
||||
function onImageBLoaded () {
|
||||
canDrawLogoB = true
|
||||
}
|
||||
|
||||
logoExchange.onload = onImageExchangeLoaded
|
||||
|
||||
function onImageExchangeLoaded () {
|
||||
canDrawLogoExchange = true
|
||||
}
|
||||
|
||||
logoAA.onload = onImageAALoaded
|
||||
|
||||
function onImageAALoaded () {
|
||||
canDrawLogoAA = true
|
||||
}
|
||||
|
||||
logoA.src = window.canvasApp.urlPrefix + 'Images/tether-logo-background.png'
|
||||
logoB.src = window.canvasApp.urlPrefix + 'Images/bitcoin-logo-background.png'
|
||||
logoExchange.src = window.canvasApp.urlPrefix + 'Images/' + exchange + '-logo-background.png'
|
||||
logoAA.src = window.canvasApp.urlPrefix + 'Images/sa-logo-background.png'
|
||||
|
||||
// moveToUserPosition(thisObject.container, timeLineCoordinateSystem, undefined, undefined, undefined, true)
|
||||
timePeriod = INITIAL_TIME_PERIOD
|
||||
datetime = NEW_SESSION_INITIAL_DATE
|
||||
|
||||
/* Event Subscriptions - we need this events to be fired first here and then in active Plotters. */
|
||||
|
||||
viewPort.eventHandler.listenToEvent('Offset Changed', onOffsetChanged)
|
||||
viewPort.eventHandler.listenToEvent('Zoom Changed', onZoomChanged)
|
||||
|
||||
/* Initialize the Plotter Manager */
|
||||
|
||||
plotterManager = newPlottersManager()
|
||||
|
||||
plotterManager.container.connectToParent(thisObject.container, true, true, false, true, true, true)
|
||||
|
||||
plotterManager.container.frame.position.x = 0
|
||||
plotterManager.container.frame.position.y = 0
|
||||
|
||||
plotterManager.fitFunction = thisObject.fitFunction
|
||||
plotterManager.initialize(productsPanel, pExchange, pMarket, onPlotterManagerReady)
|
||||
|
||||
function onPlotterManagerReady (err) {
|
||||
if (INFO_LOG === true) { logger.write('[INFO] initialize -> onPlotterManagerReady -> Entering function.') }
|
||||
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> onPlotterManagerReady -> Plotter Manager Initialization Failed. ') }
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> onPlotterManagerReady -> err= ' + err.stack) }
|
||||
|
||||
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
return
|
||||
}
|
||||
|
||||
timePeriodScale = newTimePeriodScale()
|
||||
timePeriodScale.container.connectToParent(thisObject.container, false, false, false, true, true, true)
|
||||
timePeriodScale.container.eventHandler.listenToEvent('Time Period Changed', function (event) {
|
||||
let currentTimePeriod = timePeriod
|
||||
timePeriod = event.timePeriod
|
||||
if (timePeriod !== currentTimePeriod) {
|
||||
plotterManager.setTimePeriod(timePeriod)
|
||||
}
|
||||
})
|
||||
|
||||
timePeriodScale.initialize(timeLineCoordinateSystem)
|
||||
|
||||
initializationReady = true
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
return
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) }
|
||||
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function onZoomChanged (event) {
|
||||
if (INFO_LOG === true) { logger.write('[INFO] onZoomChanged -> Entering function.') }
|
||||
function finalizeRateScale () {
|
||||
if (thisObject.rateScale === undefined) { return }
|
||||
|
||||
if (initializationReady === true) {
|
||||
recalculateCurrentDatetime()
|
||||
thisObject.rateScale.container.eventHandler.stopListening(rateScaleOffsetEventSuscriptionId)
|
||||
thisObject.rateScale.container.eventHandler.stopListening(rateScaleValueEventSuscriptionId)
|
||||
thisObject.rateScale.container.eventHandler.stopListening(rateScaleMouseOverEventSuscriptionId)
|
||||
thisObject.container.parentContainer.eventHandler.stopListening(rateScaleUpstreamEventSuscriptionId)
|
||||
thisObject.container.parentContainer.eventHandler.stopListening(rateScaleUpstreamDimensionsEventSuscriptionId)
|
||||
thisObject.rateScale.finalize()
|
||||
thisObject.rateScale = undefined
|
||||
|
||||
// saveUserPosition(thisObject.container, timeLineCoordinateSystem)
|
||||
/* Resets the local container with the dimessions of its parent, the Time Machine */
|
||||
thisObject.container.frame.position.x = 0
|
||||
thisObject.container.frame.position.y = 0
|
||||
thisObject.container.frame.height = TIME_MACHINE_HEIGHT
|
||||
thisObject.container.frame.width = TIME_MACHINE_WIDTH
|
||||
}
|
||||
|
||||
function initialize (pTimeMachineCoordinateSystem) {
|
||||
/* We load the logow we will need for the background. */
|
||||
|
||||
timeMachineCoordinateSystem = pTimeMachineCoordinateSystem
|
||||
coordinateSystem = timeMachineCoordinateSystem
|
||||
onScaleChanged()
|
||||
|
||||
timeFrame = INITIAL_TIME_PERIOD
|
||||
|
||||
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseNotOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
scaleChangedEventSubscriptionId = timeMachineCoordinateSystem.eventHandler.listenToEvent('Scale Changed', onScaleChanged)
|
||||
}
|
||||
|
||||
function initializeLayersManager () {
|
||||
let owner = thisObject.payload.node.payload.parentNode.id // The real owner is the Time Machine
|
||||
layersPanelHandle = canvas.panelsSpace.createNewPanel('Layers Panel', undefined, owner)
|
||||
thisObject.layersManager = canvas.panelsSpace.getPanel(layersPanelHandle)
|
||||
thisObject.layersManager.payload = thisObject.payload.node.layersManager.payload
|
||||
thisObject.layersManager.initialize()
|
||||
|
||||
/* Initialize the Plotter Manager */
|
||||
thisObject.plotterManager = newPlottersManager()
|
||||
|
||||
thisObject.plotterManager.container.connectToParent(thisObject.container, true, true, false, true, true, true, false, false, true)
|
||||
|
||||
thisObject.plotterManager.container.frame.position.x = 0
|
||||
thisObject.plotterManager.container.frame.position.y = 0
|
||||
|
||||
thisObject.plotterManager.fitFunction = thisObject.fitFunction
|
||||
thisObject.plotterManager.payload = thisObject.payload
|
||||
thisObject.plotterManager.initialize(thisObject.layersManager)
|
||||
thisObject.plotterManager.setTimeFrame(timeFrame)
|
||||
thisObject.plotterManager.setDatetime(datetime)
|
||||
thisObject.plotterManager.setCoordinateSystem(coordinateSystem)
|
||||
}
|
||||
|
||||
function initializeRateScale () {
|
||||
thisObject.rateScale = newRateScale()
|
||||
thisObject.rateScale.fitFunction = thisObject.fitFunction
|
||||
thisObject.rateScale.payload = thisObject.payload.node.rateScale.payload
|
||||
|
||||
rateScaleOffsetEventSuscriptionId = thisObject.rateScale.container.eventHandler.listenToEvent('Rate Scale Offset Changed', rateScaleOffsetChanged)
|
||||
rateScaleValueEventSuscriptionId = thisObject.rateScale.container.eventHandler.listenToEvent('Rate Scale Value Changed', rateScaleValueChanged)
|
||||
rateScaleMouseOverEventSuscriptionId = thisObject.rateScale.container.eventHandler.listenToEvent('onMouseOverScale', rateScaleMouseOver)
|
||||
rateScaleUpstreamEventSuscriptionId = thisObject.container.parentContainer.eventHandler.listenToEvent('Upstream Rate Scale Value Changed', rateScaleUpstreamChanged)
|
||||
rateScaleUpstreamDimensionsEventSuscriptionId = thisObject.container.parentContainer.eventHandler.listenToEvent('Dimmensions Changed', rateScaleUpstreamDimensioinsChanged)
|
||||
thisObject.rateScale.initialize(timelineChartCoordinateSystem, thisObject.container.parentContainer, thisObject.container)
|
||||
|
||||
function rateScaleUpstreamDimensioinsChanged () {
|
||||
thisObject.container.frame.height = TIME_MACHINE_HEIGHT + TIME_MACHINE_HEIGHT * thisObject.rateScale.scale
|
||||
recalculateCoordinateSystem()
|
||||
thisObject.container.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
}
|
||||
|
||||
function rateScaleUpstreamChanged (event) {
|
||||
// thisObject.rateScale.setScale(event.scale)
|
||||
}
|
||||
|
||||
function rateScaleOffsetChanged (event) {
|
||||
if (thisObject.container.frame.offset.y !== event.offset) {
|
||||
thisObject.container.frame.offset.y = event.offset
|
||||
thisObject.container.eventHandler.raiseEvent('onDisplace')
|
||||
}
|
||||
}
|
||||
|
||||
function rateScaleValueChanged (event) {
|
||||
thisObject.container.frame.height = TIME_MACHINE_HEIGHT + TIME_MACHINE_HEIGHT * event.scale
|
||||
recalculateCoordinateSystem()
|
||||
thisObject.container.eventHandler.raiseEvent('Dimmensions Changed', event)
|
||||
}
|
||||
|
||||
function rateScaleMouseOver (event) {
|
||||
thisObject.container.eventHandler.raiseEvent('onChildrenMouseOver', event)
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTimeFrameScale () {
|
||||
thisObject.timeFrameScale = newTimeFrameScale()
|
||||
thisObject.timeFrameScale.fitFunction = thisObject.fitFunction
|
||||
thisObject.timeFrameScale.payload = thisObject.payload.node.timeFrameScale.payload
|
||||
|
||||
timeFrameScaleEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('Time Frame Value Changed', timeFrameScaleValueChanged)
|
||||
timeFrameScaleMouseOverEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('onMouseOverScale', timeFrameScaleMouseOver)
|
||||
thisObject.timeFrameScale.initialize(thisObject.container.parentContainer)
|
||||
|
||||
function timeFrameScaleValueChanged (event) {
|
||||
let currentTimeFrame = timeFrame
|
||||
timeFrame = event.timeFrame
|
||||
if (timeFrame !== currentTimeFrame) {
|
||||
if (thisObject.plotterManager !== undefined) {
|
||||
thisObject.plotterManager.setTimeFrame(timeFrame)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function timeFrameScaleMouseOver (event) {
|
||||
thisObject.container.eventHandler.raiseEvent('onChildrenMouseOver', event)
|
||||
}
|
||||
}
|
||||
|
||||
function onScaleChanged () {
|
||||
timelineChartCoordinateSystem.min.x = timeMachineCoordinateSystem.min.x
|
||||
timelineChartCoordinateSystem.max.x = timeMachineCoordinateSystem.max.x
|
||||
timelineChartCoordinateSystem.recalculateScale()
|
||||
}
|
||||
|
||||
function setTimeFrame (pTimeFrame) {
|
||||
timeFrame = pTimeFrame
|
||||
if (thisObject.plotterManager !== undefined) {
|
||||
thisObject.plotterManager.setTimeFrame(timeFrame)
|
||||
}
|
||||
}
|
||||
|
||||
function setDatetime (pDatetime) {
|
||||
if (INFO_LOG === true) { logger.write('[INFO] setDatetime -> Entering function.') }
|
||||
|
||||
/* This function is used when the time is changed through the user interface, but without zooming or panning. */
|
||||
/* No matter if the day changed or not, we need to inform all visible Plotters. */
|
||||
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
plotterManager.setDatetime(pDatetime)
|
||||
plotterManager.positionAtDatetime(pDatetime)
|
||||
datetime = pDatetime
|
||||
if (thisObject.plotterManager !== undefined) {
|
||||
thisObject.plotterManager.setDatetime(datetime)
|
||||
}
|
||||
}
|
||||
|
||||
function onOffsetChanged () {
|
||||
if (INFO_LOG === true) { logger.write('[INFO] onOffsetChanged -> Entering function.') }
|
||||
function onMouseOver (event) {
|
||||
/* This event gets to the timelinechart container because it inherits it from the time machine container, which is the one raising Mouse Over and Mouse not Over Events to its children. */
|
||||
drawScales = true
|
||||
|
||||
if (initializationReady === true) {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
recalculateCurrentDatetime()
|
||||
// saveUserPosition(thisObject.container, timeLineCoordinateSystem)
|
||||
}
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
thisObject.rateScale.onMouseOverSomeTimeMachineContainer(event)
|
||||
}
|
||||
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
thisObject.timeFrameScale.onMouseOverSomeTimeMachineContainer(event)
|
||||
}
|
||||
|
||||
mouse.position.x = event.x
|
||||
mouse.position.y = event.y
|
||||
}
|
||||
|
||||
function onMouseNotOver (event) {
|
||||
/* This event is inherited from the Time Machine */
|
||||
drawScales = false
|
||||
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
thisObject.rateScale.visible = false
|
||||
}
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
thisObject.timeFrameScale.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
function recalculateCurrentDatetime () {
|
||||
if (INFO_LOG === true) { logger.write('[INFO] recalculateCurrentDatetime -> Entering function.') }
|
||||
|
||||
/*
|
||||
|
||||
The view port was moved or the view port zoom level was changed and the center of the screen points to a different datetime that we
|
||||
must calculate.
|
||||
|
||||
*/
|
||||
|
||||
let center = {
|
||||
x: (viewPort.visibleArea.bottomRight.x - viewPort.visibleArea.bottomLeft.x) / 2,
|
||||
y: (viewPort.visibleArea.bottomRight.y - viewPort.visibleArea.topRight.y) / 2
|
||||
}
|
||||
|
||||
center = unTransformThisPoint(center, thisObject.container)
|
||||
center = timeLineCoordinateSystem.unInverseTransform(center, thisObject.container.frame.height)
|
||||
|
||||
let newDate = new Date(0)
|
||||
newDate.setUTCSeconds(center.x / 1000)
|
||||
|
||||
datetime = newDate
|
||||
|
||||
plotterManager.setDatetime(datetime)
|
||||
|
||||
thisObject.container.eventHandler.raiseEvent('Datetime Changed', datetime)
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (INFO_LOG === true) { logger.write('[INFO] getContainer -> Entering function.') }
|
||||
|
||||
function getContainer (point, purpose) {
|
||||
let container
|
||||
|
||||
container = timePeriodScale.getContainer(point)
|
||||
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) {
|
||||
container = thisObject.rateScale.getContainer(point)
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (container !== undefined) { return container }
|
||||
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) {
|
||||
container = thisObject.timeFrameScale.getContainer(point)
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return container
|
||||
}
|
||||
@@ -249,283 +315,113 @@ function newTimelineChart () {
|
||||
function physics () {
|
||||
thisObjectPhysics()
|
||||
childrenPhysics()
|
||||
syncWithDesignerScales()
|
||||
syncWithDesignerLayersManager()
|
||||
}
|
||||
|
||||
function thisObjectPhysics () {
|
||||
|
||||
}
|
||||
|
||||
function childrenPhysics () {
|
||||
function syncWithDesignerLayersManager () {
|
||||
if (thisObject.payload.node === undefined) {
|
||||
finalizeLayersManager()
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function tooTiny () {
|
||||
if (viewPort.zoomLevel < Math.trunc(-28.25 * 100) / 100) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
if (thisObject.payload.node.layersManager === undefined && thisObject.layersManager !== undefined) {
|
||||
finalizeLayersManager()
|
||||
}
|
||||
if (thisObject.payload.node.layersManager !== undefined && thisObject.layersManager === undefined) {
|
||||
initializeLayersManager()
|
||||
}
|
||||
}
|
||||
|
||||
function tooSmall () {
|
||||
if (viewPort.zoomLevel < Math.trunc(-27.25 * 100) / 100) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
function syncWithDesignerScales () {
|
||||
if (thisObject.payload.node === undefined) {
|
||||
finalizeRateScale()
|
||||
finalizeTimeFrameScale()
|
||||
return
|
||||
}
|
||||
if (thisObject.payload.node.rateScale === undefined && thisObject.rateScale !== undefined) {
|
||||
finalizeRateScale()
|
||||
coordinateSystem = timeMachineCoordinateSystem
|
||||
}
|
||||
if (thisObject.payload.node.rateScale !== undefined && thisObject.rateScale === undefined) {
|
||||
initializeRateScale()
|
||||
coordinateSystem = timelineChartCoordinateSystem
|
||||
}
|
||||
if (thisObject.payload.node.timeFrameScale === undefined && thisObject.timeFrameScale !== undefined) {
|
||||
finalizeTimeFrameScale()
|
||||
}
|
||||
if (thisObject.payload.node.timeFrameScale !== undefined && thisObject.timeFrameScale === undefined) {
|
||||
initializeTimeFrameScale()
|
||||
}
|
||||
}
|
||||
|
||||
function childrenPhysics () {
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
thisObject.rateScale.layersOn = thisObject.plotterManager.connectors.length
|
||||
thisObject.rateScale.physics()
|
||||
}
|
||||
if (thisObject.timeFrameScale !== undefined) {
|
||||
thisObject.timeFrameScale.layersOn = thisObject.plotterManager.connectors.length
|
||||
thisObject.timeFrameScale.physics()
|
||||
}
|
||||
}
|
||||
|
||||
function drawBackground () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
if (window.CHART_ON_FOCUS === '') {
|
||||
window.CHART_ON_FOCUS = exchange + ' ' + market.assetB + '/' + market.assetA
|
||||
|
||||
drawChartsBackgroundImages()
|
||||
drawChartsBackground()
|
||||
if (thisObject.plotterManager !== undefined) {
|
||||
thisObject.plotterManager.draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
drawChartsBackground()
|
||||
plotterManager.draw()
|
||||
timePeriodScale.draw()
|
||||
if (drawScales === true) {
|
||||
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.draw() }
|
||||
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.draw() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawForeground () {
|
||||
if (thisObject.container.frame.isInViewPort()) {
|
||||
if (drawScales === true) {
|
||||
if (thisObject.timeFrameScale !== undefined && thisObject.timeFrameScale.isVisible === true) { thisObject.timeFrameScale.drawForeground() }
|
||||
if (thisObject.rateScale !== undefined && thisObject.rateScale.isVisible === true) { thisObject.rateScale.drawForeground() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawChartsBackground () {
|
||||
/* We will paint some transparent background here. */
|
||||
|
||||
let opacity = '0.9'
|
||||
|
||||
let fromPoint = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let toPoint = {
|
||||
x: thisObject.container.frame.width,
|
||||
y: thisObject.container.frame.height
|
||||
}
|
||||
|
||||
fromPoint = transformThisPoint(fromPoint, thisObject.container)
|
||||
toPoint = transformThisPoint(toPoint, thisObject.container)
|
||||
|
||||
fromPoint = canvas.chartSpace.fitIntoVisibleArea(fromPoint)
|
||||
toPoint = canvas.chartSpace.fitIntoVisibleArea(toPoint)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
|
||||
browserCanvasContext.rect(fromPoint.x, fromPoint.y, toPoint.x - fromPoint.x, toPoint.y - fromPoint.y)
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + opacity + ')'
|
||||
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fill()
|
||||
drawContainerBackground(thisObject.container, UI_COLOR.WHITE, 0, thisObject.fitFunction)
|
||||
}
|
||||
|
||||
function drawChartsBackgroundImages () {
|
||||
if (canDrawLogoA === false || canDrawLogoB === false || canDrawLogoExchange === false || canDrawLogoAA === false) { return }
|
||||
|
||||
/* Fist we calculate the corners of the current frame so as not to draw imaages ourside of it */
|
||||
|
||||
let fromPoint = {
|
||||
x: 0,
|
||||
function recalculateCoordinateSystem () {
|
||||
let minValue = {
|
||||
x: timelineChartCoordinateSystem.min.x,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let toPoint = {
|
||||
x: thisObject.container.frame.width,
|
||||
y: thisObject.container.frame.height
|
||||
let maxValue = {
|
||||
x: timelineChartCoordinateSystem.max.x,
|
||||
y: nextPorwerOf10(MAX_DEFAULT_RATE_SCALE_VALUE) / 4
|
||||
}
|
||||
|
||||
fromPoint = transformThisPoint(fromPoint, thisObject.container)
|
||||
toPoint = transformThisPoint(toPoint, thisObject.container)
|
||||
|
||||
/* Second we calculate the points for the images themselves */
|
||||
|
||||
let backgroundLogoPoint1
|
||||
let backgroundLogoPoint2
|
||||
|
||||
let imageHeight = 42
|
||||
let imageWidth = 150
|
||||
|
||||
const MAX_COLUMNS = 32
|
||||
const MAX_ROWS = 5
|
||||
const Y_TOP_MARGIN = 30
|
||||
const MIN_ROW_HIGHT = 100
|
||||
|
||||
let point1 = {
|
||||
x: viewPort.visibleArea.topLeft.x,
|
||||
y: viewPort.visibleArea.topLeft.y
|
||||
if (thisObject.rateScale !== undefined) {
|
||||
minValue.y = thisObject.rateScale.minValue
|
||||
maxValue.y = thisObject.rateScale.maxValue
|
||||
}
|
||||
|
||||
backgroundLogoPoint1 = {
|
||||
x: getDateFromPoint(point1, thisObject.container, timeLineCoordinateSystem).valueOf(),
|
||||
y: getRateFromPoint(point1, thisObject.container, timeLineCoordinateSystem)
|
||||
}
|
||||
|
||||
let point2 = {
|
||||
x: viewPort.visibleArea.topLeft.x + imageWidth * 8,
|
||||
y: viewPort.visibleArea.topLeft.y
|
||||
}
|
||||
|
||||
backgroundLogoPoint2 = {
|
||||
x: getDateFromPoint(point2, thisObject.container, timeLineCoordinateSystem).valueOf(),
|
||||
y: getRateFromPoint(point2, thisObject.container, timeLineCoordinateSystem)
|
||||
}
|
||||
|
||||
let currentCorner = {
|
||||
x: getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem).valueOf(),
|
||||
y: getRateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem)
|
||||
}
|
||||
|
||||
currentCorner.x = Math.trunc(currentCorner.x / (backgroundLogoPoint2.x - backgroundLogoPoint1.x)) * (backgroundLogoPoint2.x - backgroundLogoPoint1.x)
|
||||
|
||||
let rowHight = (viewPort.visibleArea.bottomLeft.y - viewPort.visibleArea.topLeft.y) / 4.5
|
||||
if (rowHight < MIN_ROW_HIGHT) { rowHight = MIN_ROW_HIGHT }
|
||||
|
||||
imagePoint = timeLineCoordinateSystem.transformThisPoint(currentCorner)
|
||||
imagePoint = transformThisPoint(imagePoint, thisObject.container)
|
||||
|
||||
let offSet = 0
|
||||
let imagePosition = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
for (let j = 0; j < MAX_ROWS; j++) {
|
||||
if (offSet === -imageWidth * 8) {
|
||||
offSet = -imageWidth * 4 - imageWidth
|
||||
} else {
|
||||
offSet = -imageWidth * 8
|
||||
}
|
||||
|
||||
for (let i = 0; i < MAX_COLUMNS; i = i + 4) {
|
||||
let logo = logoA
|
||||
|
||||
imagePosition.x = imagePoint.x + i * imageWidth * 2 + offSet
|
||||
imagePosition.y = imagePoint.y + j * rowHight + Y_TOP_MARGIN
|
||||
|
||||
if (
|
||||
imagePosition.x > fromPoint.x &&
|
||||
imagePosition.x + imageWidth < toPoint.x &&
|
||||
imagePosition.y > fromPoint.y &&
|
||||
imagePosition.y + imageHeight < toPoint.y
|
||||
) {
|
||||
let checkPoint = {
|
||||
x: imagePosition.x,
|
||||
y: imagePosition.y + imageHeight
|
||||
}
|
||||
|
||||
checkPoint = thisObject.fitFunction(checkPoint)
|
||||
if (checkPoint.y === imagePosition.y + imageHeight) {
|
||||
browserCanvasContext.drawImage(logo, imagePosition.x, imagePosition.y, imageWidth, imageHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offSet = 0
|
||||
|
||||
for (let j = 0; j < MAX_ROWS; j++) {
|
||||
if (offSet === -imageWidth * 8) {
|
||||
offSet = -imageWidth * 4 - imageWidth
|
||||
} else {
|
||||
offSet = -imageWidth * 8
|
||||
}
|
||||
|
||||
for (let i = 1; i < MAX_COLUMNS; i = i + 4) {
|
||||
let logo = logoB
|
||||
|
||||
imagePosition.x = imagePoint.x + i * imageWidth * 2 + offSet
|
||||
imagePosition.y = imagePoint.y + j * rowHight + Y_TOP_MARGIN
|
||||
|
||||
if (
|
||||
imagePosition.x > fromPoint.x &&
|
||||
imagePosition.x + imageWidth < toPoint.x &&
|
||||
imagePosition.y > fromPoint.y &&
|
||||
imagePosition.y + imageHeight < toPoint.y
|
||||
) {
|
||||
let checkPoint = {
|
||||
x: imagePosition.x,
|
||||
y: imagePosition.y + imageHeight
|
||||
}
|
||||
|
||||
checkPoint = thisObject.fitFunction(checkPoint)
|
||||
if (checkPoint.y === imagePosition.y + imageHeight) {
|
||||
browserCanvasContext.drawImage(logo, imagePosition.x, imagePosition.y, imageWidth, imageHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offSet = 0
|
||||
|
||||
for (let j = 0; j < MAX_ROWS; j++) {
|
||||
if (offSet === -imageWidth * 8) {
|
||||
offSet = -imageWidth * 4 - imageWidth
|
||||
} else {
|
||||
offSet = -imageWidth * 8
|
||||
}
|
||||
|
||||
for (let i = 2; i < MAX_COLUMNS; i = i + 4) {
|
||||
let logo = logoExchange
|
||||
|
||||
imagePosition.x = imagePoint.x + i * imageWidth * 2 + offSet
|
||||
imagePosition.y = imagePoint.y + j * rowHight + Y_TOP_MARGIN
|
||||
|
||||
if (
|
||||
imagePosition.x > fromPoint.x &&
|
||||
imagePosition.x + imageWidth < toPoint.x &&
|
||||
imagePosition.y > fromPoint.y &&
|
||||
imagePosition.y + imageHeight < toPoint.y
|
||||
) {
|
||||
let checkPoint = {
|
||||
x: imagePosition.x,
|
||||
y: imagePosition.y + imageHeight
|
||||
}
|
||||
|
||||
checkPoint = thisObject.fitFunction(checkPoint)
|
||||
if (checkPoint.y === imagePosition.y + imageHeight) {
|
||||
browserCanvasContext.drawImage(logo, imagePosition.x, imagePosition.y, imageWidth, imageHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offSet = 0
|
||||
|
||||
for (let j = 0; j < MAX_ROWS; j++) {
|
||||
if (offSet === -imageWidth * 8) {
|
||||
offSet = -imageWidth * 4 - imageWidth
|
||||
} else {
|
||||
offSet = -imageWidth * 8
|
||||
}
|
||||
|
||||
for (let i = 3; i < MAX_COLUMNS; i = i + 4) {
|
||||
let logo = logoAA
|
||||
|
||||
imagePosition.x = imagePoint.x + i * imageWidth * 2 + offSet
|
||||
imagePosition.y = imagePoint.y + j * rowHight + Y_TOP_MARGIN
|
||||
|
||||
if (
|
||||
imagePosition.x > fromPoint.x &&
|
||||
imagePosition.x + imageWidth < toPoint.x &&
|
||||
imagePosition.y > fromPoint.y &&
|
||||
imagePosition.y + imageHeight < toPoint.y
|
||||
) {
|
||||
let checkPoint = {
|
||||
x: imagePosition.x,
|
||||
y: imagePosition.y + imageHeight
|
||||
}
|
||||
|
||||
checkPoint = thisObject.fitFunction(checkPoint)
|
||||
if (checkPoint.y === imagePosition.y + imageHeight) {
|
||||
browserCanvasContext.drawImage(logo, imagePosition.x, imagePosition.y, imageWidth, imageHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timelineChartCoordinateSystem.initialize(
|
||||
minValue,
|
||||
maxValue,
|
||||
thisObject.container.frame.width,
|
||||
thisObject.container.frame.height
|
||||
)
|
||||
}
|
||||
}
|
||||
+200
-285
@@ -1,20 +1,17 @@
|
||||
|
||||
function newViewPort () {
|
||||
function newViewport () {
|
||||
const MODULE_NAME = 'Viewport'
|
||||
const INFO_LOG = false
|
||||
const INTENSIVE_LOG = false
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
const CONSOLE_LOG = true
|
||||
const MIN_ZOOM_LEVEL = 0
|
||||
const MAX_ZOOM_LEVEL = 500
|
||||
|
||||
let ANIMATION_INCREMENT = 0.25
|
||||
let ANIMATION_STEPS = 5
|
||||
|
||||
let TOP_MARGIN = 30 + TOP_SPACE_HEIGHT
|
||||
let BOTTOM_MARGIN = 30 + COCKPIT_SPACE_HEIGHT
|
||||
let LEFT_MARGIN = 50
|
||||
let RIGHT_MARGIN = 50
|
||||
let TOP_MARGIN = 40 + TOP_SPACE_HEIGHT
|
||||
let BOTTOM_MARGIN = 42 + COCKPIT_SPACE_HEIGHT
|
||||
let LEFT_MARGIN = 0
|
||||
let RIGHT_MARGIN = 0
|
||||
let MARGINS = {
|
||||
TOP: TOP_MARGIN,
|
||||
BOTTOM: BOTTOM_MARGIN,
|
||||
@@ -31,60 +28,78 @@ function newViewPort () {
|
||||
zoomLevel: undefined,
|
||||
mousePosition: undefined,
|
||||
margins: MARGINS,
|
||||
getDisplacement: getDisplacement,
|
||||
newZoomLevel: newZoomLevel,
|
||||
applyZoom: applyZoom,
|
||||
isMinZoom: isMinZoom,
|
||||
zoomFontSize: zoomFontSize,
|
||||
zoomThisPoint: zoomThisPoint,
|
||||
unzoomThisPoint: unzoomThisPoint,
|
||||
payload: undefined,
|
||||
changeZoom: changeZoom,
|
||||
onMouseWheel: onMouseWheel,
|
||||
transformThisPoint: transformThisPoint,
|
||||
unTransformThisPoint: unTransformThisPoint,
|
||||
isThisPointVisible: isThisPointVisible,
|
||||
fitIntoVisibleArea: fitIntoVisibleArea,
|
||||
displace: displace,
|
||||
displaceTarget: displaceTarget,
|
||||
animate: animate,
|
||||
draw: draw,
|
||||
physics: physics,
|
||||
raiseEvents: raiseEvents,
|
||||
resize: resize,
|
||||
initialize: initialize
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let increment = 0.035
|
||||
|
||||
let offset = {
|
||||
let position = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
var targetOffset = {
|
||||
let targetPosition = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let offsetIncrement = {
|
||||
let positionIncrement = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.mousePosition = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.eventHandler = newEventHandler()
|
||||
|
||||
let objectStorage = {}
|
||||
/* Initial default value */
|
||||
thisObject.zoomLevel = MIN_ZOOM_LEVEL
|
||||
thisObject.zoomTargetLevel = MIN_ZOOM_LEVEL
|
||||
INITIAL_TIME_PERIOD = recalculatePeriod(thisObject.zoomLevel)
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.eventHandler.finalize()
|
||||
thisObject.payload = undefined
|
||||
thisObject = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
if (thisObject.payload !== undefined) {
|
||||
/* Read the position from the frame structure */
|
||||
|
||||
let frame = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
loadFrame(thisObject.payload, frame)
|
||||
if (!isNaN(frame.position.x)) {
|
||||
position.x = frame.position.x
|
||||
}
|
||||
if (!isNaN(frame.position.y)) {
|
||||
position.y = frame.position.y
|
||||
}
|
||||
}
|
||||
|
||||
resize()
|
||||
readObjectState()
|
||||
}
|
||||
|
||||
function resize () {
|
||||
TOP_MARGIN = 30 + TOP_SPACE_HEIGHT
|
||||
BOTTOM_MARGIN = 30 + browserCanvas.height - COCKPIT_SPACE_POSITION
|
||||
TOP_MARGIN = 40 + TOP_SPACE_HEIGHT
|
||||
BOTTOM_MARGIN = 42 + browserCanvas.height - COCKPIT_SPACE_POSITION
|
||||
LEFT_MARGIN = 0
|
||||
RIGHT_MARGIN = 0
|
||||
MARGINS = {
|
||||
@@ -103,25 +118,36 @@ function newViewPort () {
|
||||
|
||||
thisObject.width = thisObject.visibleArea.topRight.x - thisObject.visibleArea.topLeft.x
|
||||
thisObject.height = thisObject.visibleArea.bottomRight.y - thisObject.visibleArea.topLeft.y
|
||||
}
|
||||
|
||||
function getDisplacement () {
|
||||
let displacement = {
|
||||
x: offset.x,
|
||||
y: offset.y
|
||||
thisObject.center = {
|
||||
x: LEFT_MARGIN + thisObject.width / 2,
|
||||
y: TOP_MARGIN + thisObject.height / 2
|
||||
}
|
||||
return displacement
|
||||
}
|
||||
|
||||
function raiseEvents () {
|
||||
let event = {
|
||||
newOffset: offset
|
||||
newPosition: position
|
||||
}
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Offset Changed', event)
|
||||
thisObject.eventHandler.raiseEvent('Position Changed', event)
|
||||
}
|
||||
|
||||
function animate () {
|
||||
function physics () {
|
||||
animationPhysics()
|
||||
positioningPhysics()
|
||||
readObjectState()
|
||||
}
|
||||
|
||||
function positioningPhysics () {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
/* Save the position at the frame lavel */
|
||||
let frame = {}
|
||||
frame.position = position
|
||||
saveFrame(thisObject.payload, frame)
|
||||
}
|
||||
|
||||
function animationPhysics () {
|
||||
if (thisObject.zoomLevel < thisObject.zoomTargetLevel) {
|
||||
if (thisObject.zoomTargetLevel - thisObject.zoomLevel < ANIMATION_INCREMENT) {
|
||||
ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel)
|
||||
@@ -138,174 +164,60 @@ function newViewPort () {
|
||||
changeZoom(thisObject.zoomLevel + ANIMATION_INCREMENT, thisObject.zoomLevel)
|
||||
}
|
||||
|
||||
if (offsetIncrement.y !== 0) {
|
||||
if (Math.trunc(Math.abs(targetOffset.y - offset.y) * 1000) >= Math.trunc(Math.abs(offsetIncrement.y) * 1000)) {
|
||||
offset.y = offset.y + offsetIncrement.y
|
||||
|
||||
// console.log("offset.y changed to " + offset.y)
|
||||
if (positionIncrement.y !== 0) {
|
||||
if (Math.trunc(Math.abs(targetPosition.y - position.y) * 1000) >= Math.trunc(Math.abs(positionIncrement.y) * 1000)) {
|
||||
position.y = position.y + positionIncrement.y
|
||||
} else {
|
||||
offsetIncrement.y = 0
|
||||
positionIncrement.y = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function displace (displaceVector, recalculate) {
|
||||
offset.x = offset.x + displaceVector.x
|
||||
offset.y = offset.y + displaceVector.y
|
||||
|
||||
saveObjectState()
|
||||
|
||||
let event = {
|
||||
newOffset: offset,
|
||||
recalculate: recalculate
|
||||
}
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Offset Changed', event)
|
||||
|
||||
// console.log("displace produced new Offset x = " + offset.x + " y = " + offset.y);
|
||||
}
|
||||
|
||||
function displaceTarget (displaceVector) {
|
||||
targetOffset.x = targetOffset.x + displaceVector.x
|
||||
targetOffset.y = targetOffset.y + displaceVector.y
|
||||
|
||||
offsetIncrement = {
|
||||
x: (targetOffset.x - offset.x) / 10,
|
||||
y: (targetOffset.y - offset.y) / 10
|
||||
}
|
||||
|
||||
// console.log("displaceTarget x = " + targetOffset.x + " y = " + targetOffset.y);
|
||||
}
|
||||
|
||||
function newZoomLevel (level) {
|
||||
thisObject.zoomTargetLevel = level
|
||||
thisObject.zoomLevel = level
|
||||
|
||||
saveObjectState()
|
||||
|
||||
ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) / 3
|
||||
|
||||
let event = {
|
||||
newLevel: thisObject.zoomTargetLevel,
|
||||
newOffset: offset,
|
||||
type: undefined
|
||||
}
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Zoom Changed', event)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
function isMinZoom () {
|
||||
/* returns true is we are currently at the min zoom level. */
|
||||
|
||||
if (thisObject.zoomTargetLevel === MIN_ZOOM_LEVEL) { return true } else { return false }
|
||||
}
|
||||
|
||||
function applyZoom (amount) {
|
||||
// console.log("applyZoom amount: " + amount);
|
||||
|
||||
function onMouseWheel (event) {
|
||||
let morePower = 1
|
||||
let amount = event.delta
|
||||
if (event.buttons === 4) { morePower = 2 } // Mouse wheel pressed.
|
||||
/* We adjust the sensitivity for Mac Users */
|
||||
let isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||
if (isMac) { amount = amount / 5 }
|
||||
|
||||
if (amount > 0) {
|
||||
if (thisObject.zoomTargetLevel > -5) {
|
||||
amount = amount * 2
|
||||
}
|
||||
|
||||
if (thisObject.zoomTargetLevel > 10) {
|
||||
amount = amount * 3
|
||||
}
|
||||
|
||||
if (thisObject.zoomTargetLevel > 15) {
|
||||
amount = amount * 4
|
||||
}
|
||||
if (thisObject.zoomTargetLevel > 10) {
|
||||
amount = amount * 2
|
||||
}
|
||||
if (thisObject.zoomTargetLevel > 25) {
|
||||
amount = amount * 3
|
||||
}
|
||||
if (thisObject.zoomTargetLevel > 50) {
|
||||
amount = amount * 3.5
|
||||
}
|
||||
|
||||
if (amount < 0) {
|
||||
if (thisObject.zoomTargetLevel > -4) {
|
||||
amount = amount * 2
|
||||
}
|
||||
|
||||
if (thisObject.zoomTargetLevel > 13) {
|
||||
amount = amount * 3
|
||||
}
|
||||
|
||||
if (thisObject.zoomTargetLevel > 19) {
|
||||
amount = amount * 4
|
||||
}
|
||||
}
|
||||
|
||||
if (thisObject.zoomTargetLevel + amount > 1000) {
|
||||
if (thisObject.zoomTargetLevel + amount * morePower > MAX_ZOOM_LEVEL) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (thisObject.zoomTargetLevel <= -27 && amount < 0) {
|
||||
amount = amount / 4
|
||||
}
|
||||
|
||||
if (thisObject.zoomTargetLevel < -27 && amount > 0) {
|
||||
amount = amount / 4
|
||||
}
|
||||
|
||||
if (thisObject.zoomTargetLevel + amount < MIN_ZOOM_LEVEL) {
|
||||
if (thisObject.zoomTargetLevel + amount * morePower < MIN_ZOOM_LEVEL) {
|
||||
return false
|
||||
}
|
||||
thisObject.zoomTargetLevel = thisObject.zoomTargetLevel + amount * morePower
|
||||
|
||||
thisObject.zoomTargetLevel = thisObject.zoomTargetLevel + amount
|
||||
ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) / ANIMATION_STEPS
|
||||
|
||||
ANIMATION_INCREMENT = Math.abs(thisObject.zoomTargetLevel - thisObject.zoomLevel) / 3
|
||||
|
||||
let event = {
|
||||
let newEvent = {
|
||||
newLevel: thisObject.zoomTargetLevel,
|
||||
newOffset: offset,
|
||||
type: undefined
|
||||
newPosition: position,
|
||||
type: undefined,
|
||||
shiftKey: event.shiftKey
|
||||
}
|
||||
|
||||
if (amount > 0) {
|
||||
event.type = 'Zoom In'
|
||||
newEvent.type = 'Zoom In'
|
||||
} else {
|
||||
event.type = 'Zoom Out'
|
||||
newEvent.type = 'Zoom Out'
|
||||
}
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Zoom Changed', event)
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Zoom Changed', newEvent)
|
||||
return true
|
||||
}
|
||||
|
||||
function changeZoom (oldLevel, newLevel) {
|
||||
let mouseNoZoom = unzoomThisPoint(thisObject.mousePosition, oldLevel)
|
||||
let newMouse = zoomThisPoint(mouseNoZoom, newLevel)
|
||||
|
||||
offset.x = offset.x - newMouse.x + thisObject.mousePosition.x
|
||||
offset.y = offset.y - newMouse.y + thisObject.mousePosition.y
|
||||
|
||||
saveObjectState()
|
||||
|
||||
targetOffset.x = offset.x
|
||||
targetOffset.y = offset.y
|
||||
|
||||
offsetIncrement = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Zoom Changed')
|
||||
}
|
||||
|
||||
function zoomFontSize (baseSize, level) {
|
||||
let zoomFactor = increment // + increment * thisObject.zoomLevel / 100;
|
||||
|
||||
if (level === undefined) {
|
||||
baseSize = baseSize * (1 + zoomFactor * thisObject.zoomLevel)
|
||||
} else {
|
||||
baseSize = baseSize * (1 + zoomFactor * level)
|
||||
}
|
||||
|
||||
return baseSize
|
||||
}
|
||||
|
||||
function fitIntoVisibleArea (point) {
|
||||
/* Here we check the boundaries of the resulting points, so they dont go out of the visible area. */
|
||||
|
||||
@@ -328,35 +240,72 @@ function newViewPort () {
|
||||
return point
|
||||
}
|
||||
|
||||
function zoomThisPoint (point, level) {
|
||||
let zoomFactor = increment // + increment * thisObject.zoomLevel / 100;
|
||||
function displace (displaceVector, recalculate) {
|
||||
position.x = position.x + displaceVector.x
|
||||
position.y = position.y + displaceVector.y
|
||||
|
||||
if (level === undefined) {
|
||||
point.x = point.x * (1 + zoomFactor * thisObject.zoomLevel) + offset.x
|
||||
point.y = point.y * (1 + zoomFactor * thisObject.zoomLevel) + offset.y
|
||||
} else {
|
||||
point.x = point.x * (1 + zoomFactor * level) + offset.x
|
||||
point.y = point.y * (1 + zoomFactor * level) + offset.y
|
||||
saveObjectState()
|
||||
|
||||
let event = {
|
||||
newPosition: position,
|
||||
recalculate: recalculate
|
||||
}
|
||||
|
||||
return point
|
||||
thisObject.eventHandler.raiseEvent('Position Changed', event)
|
||||
}
|
||||
|
||||
function unzoomThisPoint (pointWithZoom, level) {
|
||||
let pointWithoutZoom
|
||||
let zoomFactor = increment // + increment * thisObject.zoomLevel / 100;
|
||||
function changeZoom (oldLevel, newLevel) {
|
||||
let oldMouse = unTransformThisPoint(thisObject.mousePosition, oldLevel)
|
||||
let newMouse = transformThisPoint(oldMouse, newLevel)
|
||||
|
||||
position.x = position.x - newMouse.x + thisObject.mousePosition.x
|
||||
position.y = position.y - newMouse.y + thisObject.mousePosition.y
|
||||
|
||||
let testPoint = unTransformThisPoint(thisObject.mousePosition, newLevel)
|
||||
|
||||
saveObjectState()
|
||||
|
||||
targetPosition.x = position.x
|
||||
targetPosition.y = position.y
|
||||
|
||||
positionIncrement = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.eventHandler.raiseEvent('Zoom Changed')
|
||||
}
|
||||
|
||||
function transformThisPoint (point, level) {
|
||||
let transformedPoint = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
if (level === undefined) {
|
||||
pointWithoutZoom = {
|
||||
x: (pointWithZoom.x - offset.x) / (1 + zoomFactor * thisObject.zoomLevel),
|
||||
y: (pointWithZoom.y - offset.y) / (1 + zoomFactor * thisObject.zoomLevel)
|
||||
}
|
||||
transformedPoint.x = point.x * (1 + thisObject.zoomLevel) + position.x
|
||||
transformedPoint.y = point.y * (1 + thisObject.zoomLevel) + position.y
|
||||
} else {
|
||||
pointWithoutZoom = {
|
||||
x: (pointWithZoom.x - offset.x) / (1 + zoomFactor * level),
|
||||
y: (pointWithZoom.y - offset.y) / (1 + zoomFactor * level)
|
||||
}
|
||||
transformedPoint.x = point.x * (1 + level) + position.x
|
||||
transformedPoint.y = point.y * (1 + level) + position.y
|
||||
}
|
||||
|
||||
return transformedPoint
|
||||
}
|
||||
|
||||
function unTransformThisPoint (point, level) {
|
||||
let pointWithoutZoom = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
if (level === undefined) {
|
||||
pointWithoutZoom.x = (point.x - position.x) / (1 + thisObject.zoomLevel)
|
||||
pointWithoutZoom.y = (point.y - position.y) / (1 + thisObject.zoomLevel)
|
||||
} else {
|
||||
pointWithoutZoom.x = (point.x - position.x) / (1 + level)
|
||||
pointWithoutZoom.y = (point.y - position.y) / (1 + level)
|
||||
}
|
||||
|
||||
return pointWithoutZoom
|
||||
}
|
||||
|
||||
@@ -372,92 +321,58 @@ function newViewPort () {
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
drawGrid(0.1)
|
||||
}
|
||||
|
||||
function drawGrid (step) {
|
||||
if (thisObject.zoomLevel > -17) { return }
|
||||
|
||||
let squareWidth = (thisObject.visibleArea.bottomRight.x - thisObject.visibleArea.bottomLeft.x) / step
|
||||
squareWidth = squareWidth + squareWidth * increment * thisObject.zoomLevel
|
||||
|
||||
let startingX = offset.x - Math.trunc(offset.x / squareWidth) * squareWidth
|
||||
let startingY = offset.y - Math.trunc(offset.y / squareWidth) * squareWidth
|
||||
let lineWidth = 0.4 + thisObject.zoomLevel / 100
|
||||
lineWidth = lineWidth.toFixed(2)
|
||||
|
||||
if (lineWidth < 0.1) {
|
||||
return
|
||||
}
|
||||
|
||||
if (lineWidth > 2) {
|
||||
lineWidth = 2
|
||||
}
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
|
||||
let CROSS_SIZE = 4
|
||||
|
||||
for (var i = startingX; i < thisObject.visibleArea.bottomRight.x + RIGHT_MARGIN; i = i + squareWidth) {
|
||||
for (var j = startingY; j < thisObject.visibleArea.bottomRight.y + BOTTOM_MARGIN; j = j + squareWidth) {
|
||||
let point1 = {
|
||||
x: Math.trunc(i - CROSS_SIZE),
|
||||
y: Math.trunc(j)
|
||||
}
|
||||
|
||||
let point2 = {
|
||||
x: Math.trunc(i + CROSS_SIZE),
|
||||
y: Math.trunc(j)
|
||||
}
|
||||
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
|
||||
let point3 = {
|
||||
x: Math.trunc(i),
|
||||
y: Math.trunc(j - CROSS_SIZE)
|
||||
}
|
||||
|
||||
let point4 = {
|
||||
x: Math.trunc(i),
|
||||
y: Math.trunc(j + CROSS_SIZE)
|
||||
}
|
||||
|
||||
browserCanvasContext.moveTo(point3.x, point3.y)
|
||||
browserCanvasContext.lineTo(point4.x, point4.y)
|
||||
}
|
||||
}
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(150, 150, 150, 0.5)'
|
||||
|
||||
browserCanvasContext.lineWidth = 1
|
||||
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
|
||||
function saveObjectState () {
|
||||
objectStorage.offset = offset
|
||||
objectStorage.zoomLevel = thisObject.zoomLevel
|
||||
window.localStorage.setItem(MODULE_NAME, JSON.stringify(objectStorage))
|
||||
if (thisObject.payload === undefined) { return }
|
||||
|
||||
/* 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)
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
}
|
||||
|
||||
function readObjectState () {
|
||||
let objectStorageString = window.localStorage.getItem(MODULE_NAME)
|
||||
if (objectStorageString !== null && objectStorageString !== '') {
|
||||
objectStorage = JSON.parse(objectStorageString)
|
||||
offset = objectStorage.offset
|
||||
thisObject.zoomLevel = objectStorage.zoomLevel
|
||||
thisObject.zoomTargetLevel = objectStorage.zoomLevel
|
||||
INITIAL_TIME_PERIOD = recalculatePeriod(thisObject.zoomLevel)
|
||||
} else { // Setting default values for first session
|
||||
offset = {
|
||||
x: 0,
|
||||
y: 0
|
||||
if (thisObject.payload === undefined) { return }
|
||||
|
||||
/* Read the zoom level from the node config */
|
||||
try {
|
||||
let code = JSON.parse(thisObject.payload.node.code)
|
||||
|
||||
if (isNaN(code.zoom) || code.zoom === null || code.zoom === undefined) {
|
||||
saveObjectState()
|
||||
return
|
||||
}
|
||||
thisObject.zoomLevel = MIN_ZOOM_LEVEL
|
||||
thisObject.zoomTargetLevel = MIN_ZOOM_LEVEL
|
||||
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 }
|
||||
|
||||
if (code.zoom.toFixed(2) !== thisObject.zoomTargetLevel.toFixed(2)) {
|
||||
newZoomLevel(code.zoom)
|
||||
} else {
|
||||
saveObjectState()
|
||||
}
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
|
||||
function newZoomLevel (level) {
|
||||
thisObject.zoomLevel = level
|
||||
thisObject.zoomTargetLevel = level
|
||||
INITIAL_TIME_PERIOD = recalculatePeriod(level)
|
||||
saveObjectState()
|
||||
ANIMATION_INCREMENT = 0
|
||||
|
||||
let event = {
|
||||
newLevel: thisObject.zoomTargetLevel,
|
||||
newPosition: position,
|
||||
type: undefined
|
||||
}
|
||||
thisObject.eventHandler.raiseEvent('Zoom Changed', event)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
function newAssetBalances () {
|
||||
function newQuotedAssetalances () {
|
||||
const MODULE_NAME = 'Asset Balances'
|
||||
|
||||
let thisObject = {
|
||||
@@ -37,9 +37,6 @@ function newAssetBalances () {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
let speedometer = newSpeedometer()
|
||||
|
||||
speedometer.container.frame.position.x = thisObject.container.frame.width / 2 - speedometer.container.frame.width / 2
|
||||
speedometer.container.frame.position.y = thisObject.container.frame.height / 2 - speedometer.container.frame.height / 2
|
||||
|
||||
speedometer.initialize()
|
||||
thisObject.speedometers.push(speedometer)
|
||||
}
|
||||
@@ -87,10 +84,10 @@ function newAssetBalances () {
|
||||
speedometer.draw()
|
||||
}
|
||||
|
||||
drawAssetBalances()
|
||||
drawQuotedAssetalances()
|
||||
}
|
||||
|
||||
function drawAssetBalances () {
|
||||
function drawQuotedAssetalances () {
|
||||
if (thisObject.paramsArray === undefined) { return }
|
||||
|
||||
let fontSize
|
||||
@@ -109,7 +106,7 @@ function newAssetBalances () {
|
||||
label = 'ASSET BALANCES'
|
||||
|
||||
xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO
|
||||
yOffset = -45
|
||||
yOffset = -45 + 9
|
||||
|
||||
labelPoint = {
|
||||
x: 0 - xOffset + (thisObject.paramsArray[1].LEFT_OFFSET - thisObject.paramsArray[0].LEFT_OFFSET) / 2 + thisObject.paramsArray[0].LEFT_OFFSET - 20,
|
||||
@@ -120,3 +117,4 @@ function newAssetBalances () {
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ function newFullScreen () {
|
||||
let isMouseOver = false
|
||||
let counterTillNextState = 0
|
||||
|
||||
let productCardsToTurnOn = []
|
||||
let layersToTurnOn = []
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
|
||||
+14
-14
@@ -51,24 +51,24 @@ function newSpeedometer () {
|
||||
}
|
||||
|
||||
function drawAssetCircle () {
|
||||
const RED_LINE_HIGHT = 5
|
||||
const RADIOUS = 50
|
||||
const RED_LINE_HIGHT = 2
|
||||
const RADIUS = 50
|
||||
const OPACITY = 1
|
||||
|
||||
let centerPoint = {
|
||||
x: thisObject.params.LEFT_OFFSET,
|
||||
y: COCKPIT_SPACE_POSITION - COCKPIT_SPACE_HEIGHT / 2
|
||||
y: COCKPIT_SPACE_POSITION - COCKPIT_SPACE_HEIGHT / 2 - 9
|
||||
}
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, RADIOUS + RED_LINE_HIGHT, 0.85 * Math.PI, 2.15 * Math.PI)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, RADIUS + RED_LINE_HIGHT, 0.85 * Math.PI, 2.15 * Math.PI)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.fill()
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, RADIOUS, 0.0 * Math.PI, 2.0 * Math.PI)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, RADIUS, 0.0 * Math.PI, 2.0 * Math.PI)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.DARK_TURQUOISE + ', ' + OPACITY + ')'
|
||||
@@ -79,7 +79,7 @@ function newSpeedometer () {
|
||||
const DEFAULT_THICKNESS = 2
|
||||
const VALUE_THICKNESS = 8
|
||||
const VALUE_BG_THICKNESS = 1
|
||||
const BAR_RADIOUS = RADIOUS * 0.85
|
||||
const BAR_RADIUS = RADIUS * 0.85
|
||||
|
||||
let BAR_START_ANGLE = 0.85 * Math.PI
|
||||
let BAR_END_ANGLE = 2.15 * Math.PI
|
||||
@@ -100,7 +100,7 @@ function newSpeedometer () {
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIOUS, BAR_START_ANGLE, MIN_VALUE_ANGLE)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, BAR_START_ANGLE, MIN_VALUE_ANGLE)
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = VALUE_BG_THICKNESS
|
||||
@@ -108,7 +108,7 @@ function newSpeedometer () {
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIOUS, MIN_VALUE_ANGLE, CURRENT_VALUE_ANGLE)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, MIN_VALUE_ANGLE, CURRENT_VALUE_ANGLE)
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = VALUE_BG_THICKNESS
|
||||
@@ -116,7 +116,7 @@ function newSpeedometer () {
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIOUS, CURRENT_VALUE_ANGLE, INIT_VALUE_ANGLE)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, CURRENT_VALUE_ANGLE, INIT_VALUE_ANGLE)
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = VALUE_BG_THICKNESS
|
||||
@@ -125,7 +125,7 @@ function newSpeedometer () {
|
||||
|
||||
if (PROFIT_VALUE_ANGLE > INIT_VALUE_ANGLE) {
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIOUS, INIT_VALUE_ANGLE, PROFIT_VALUE_ANGLE)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, INIT_VALUE_ANGLE, PROFIT_VALUE_ANGLE)
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = VALUE_BG_THICKNESS
|
||||
@@ -136,7 +136,7 @@ function newSpeedometer () {
|
||||
browserCanvasContext.setLineDash([2, 3])
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIOUS, BAR_START_ANGLE, MIN_VALUE_ANGLE)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, BAR_START_ANGLE, MIN_VALUE_ANGLE)
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = VALUE_THICKNESS
|
||||
@@ -144,7 +144,7 @@ function newSpeedometer () {
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIOUS, MIN_VALUE_ANGLE, CURRENT_VALUE_ANGLE)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, MIN_VALUE_ANGLE, CURRENT_VALUE_ANGLE)
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.WHITE + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = VALUE_THICKNESS
|
||||
@@ -152,7 +152,7 @@ function newSpeedometer () {
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIOUS, CURRENT_VALUE_ANGLE, INIT_VALUE_ANGLE)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, CURRENT_VALUE_ANGLE, INIT_VALUE_ANGLE)
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RED + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = VALUE_THICKNESS
|
||||
@@ -161,7 +161,7 @@ function newSpeedometer () {
|
||||
|
||||
if (PROFIT_VALUE_ANGLE > INIT_VALUE_ANGLE) {
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIOUS, INIT_VALUE_ANGLE, PROFIT_VALUE_ANGLE)
|
||||
browserCanvasContext.arc(centerPoint.x, centerPoint.y, BAR_RADIUS, INIT_VALUE_ANGLE, PROFIT_VALUE_ANGLE)
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GREEN + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = VALUE_THICKNESS
|
||||
|
||||
+10
-7
@@ -4,7 +4,6 @@ function newContainer () {
|
||||
id: Math.trunc(Math.random() * 10000000),
|
||||
type: 'Rectangle',
|
||||
frame: undefined,
|
||||
displacement: undefined,
|
||||
eventHandler: undefined,
|
||||
parentContainer: undefined,
|
||||
isDraggeable: true,
|
||||
@@ -62,6 +61,8 @@ function newContainer () {
|
||||
|
||||
thisObject.parentContainer = undefined
|
||||
thisObject.eventHandler.finalize()
|
||||
|
||||
thisObject.frame.finalize()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,15 +72,13 @@ function newContainer () {
|
||||
|
||||
thisObject.frame = newFrame()
|
||||
thisObject.frame.initialize(pType)
|
||||
thisObject.frame.containerName = pName
|
||||
if (pName !== undefined) {
|
||||
thisObject.frame.containerName = pName
|
||||
}
|
||||
thisObject.frame.container = thisObject
|
||||
|
||||
thisObject.eventHandler = newEventHandler()
|
||||
thisObject.eventHandler.name = pName
|
||||
|
||||
thisObject.displacement = newDisplacement()
|
||||
thisObject.displacement.container = thisObject
|
||||
thisObject.displacement.containerName = pName
|
||||
}
|
||||
|
||||
function connectToParent (
|
||||
@@ -111,7 +110,6 @@ function newContainer () {
|
||||
|
||||
isConnectedToParent = true
|
||||
|
||||
thisObject.displacement.parentDisplacement = parentContainer.displacement
|
||||
thisObject.frame.parentFrame = parentContainer.frame
|
||||
thisObject.parentContainer = parentContainer
|
||||
|
||||
@@ -217,6 +215,11 @@ function newContainer () {
|
||||
return true
|
||||
}
|
||||
break
|
||||
case GET_CONTAINER_PURPOSE.DRAGGING:
|
||||
if (thisObject.isDraggeable === true) {
|
||||
return true
|
||||
}
|
||||
break
|
||||
default: { return false }
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ function newSidePanel () {
|
||||
thisObject.sidePanelTab.container.connectToParent(thisObject.container, false, false)
|
||||
thisObject.sidePanelTab.initialize()
|
||||
|
||||
window.canvasApp.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
|
||||
+9
-45
@@ -2,7 +2,7 @@ let canvas
|
||||
let markets
|
||||
let ecosystem = newEcosystem()
|
||||
let systemEventHandler
|
||||
let viewPort
|
||||
|
||||
let APP_SCHEMA_MAP = new Map()
|
||||
let APP_SCHEMA_ARRAY = []
|
||||
|
||||
@@ -19,17 +19,12 @@ function newDashboard () {
|
||||
|
||||
const DEBUG_START_UP_DELAY = 0 // 3000; // This is a waiting time in case there is a need to debug the very first steps of initialization, to be able to hit F12 on time.
|
||||
|
||||
let userProfileChangedEventSubscriptionId
|
||||
let browserResizedEventSubscriptionId
|
||||
|
||||
return thisObject
|
||||
|
||||
function start () {
|
||||
try {
|
||||
setBrowserEvents()
|
||||
|
||||
viewPort = newViewPort()
|
||||
|
||||
systemEventHandler = newSystemEventHandler()
|
||||
systemEventHandler.initialize(setUpAppSchema)
|
||||
|
||||
@@ -37,12 +32,8 @@ function newDashboard () {
|
||||
APP_SCHEMA_ARRAY = getAppSchema()
|
||||
for (let i = 0; i < APP_SCHEMA_ARRAY.length; i++) {
|
||||
let nodeDefinition = APP_SCHEMA_ARRAY[i]
|
||||
let key
|
||||
if (nodeDefinition.subType !== undefined) {
|
||||
key = nodeDefinition.type + '-' + nodeDefinition.subType
|
||||
} else {
|
||||
key = nodeDefinition.type
|
||||
}
|
||||
let key = nodeDefinition.type
|
||||
|
||||
APP_SCHEMA_MAP.set(key, nodeDefinition)
|
||||
}
|
||||
|
||||
@@ -54,22 +45,16 @@ function newDashboard () {
|
||||
|
||||
if (canvas !== undefined) { canvas.finalize() }
|
||||
|
||||
/* Here we check where we are executing. In case we are Local we need to create a Local Dummy User and Team. */
|
||||
/* Here we check where we are executing. In case we are Local we need to create a Local Dummy User and Data Mine. */
|
||||
|
||||
if (window.canvasApp.executingAt === 'Local') {
|
||||
window.localStorage.setItem(LOGGED_IN_ACCESS_TOKEN_LOCAL_STORAGE_KEY, 'Local Access Token') // Dummy Access Token
|
||||
window.localStorage.setItem(LOGGED_IN_USER_LOCAL_STORAGE_KEY, '{"authId":"x|x","alias":"user"}') // Dummy Local User
|
||||
}
|
||||
|
||||
/* Here we will setup the global eventHandler that will enable the Canvas App to react to events happening outside its execution scope. */
|
||||
/* Here we used to have a call to the DataMines Module to get the profile pictures. That was removed but to keep things working, we do this: */
|
||||
|
||||
window.canvasApp.eventHandler = newEventHandler()
|
||||
userProfileChangedEventSubscriptionId = window.canvasApp.eventHandler.listenToEvent('User Profile Changed', userProfileChanged)
|
||||
browserResizedEventSubscriptionId = window.canvasApp.eventHandler.listenToEvent('Browser Resized', browserResized)
|
||||
|
||||
/* Here we used to have a call to the Teams Module to get the profile pictures. That was removed but to keep things working, we do this: */
|
||||
|
||||
window.canvasApp.context.teamProfileImages = new Map()
|
||||
window.canvasApp.context.dataMineProfileImages = new Map()
|
||||
window.canvasApp.context.fbProfileImages = new Map()
|
||||
|
||||
setTimeout(delayedStart, DEBUG_START_UP_DELAY)
|
||||
@@ -85,8 +70,8 @@ function newDashboard () {
|
||||
|
||||
let market = {
|
||||
id: 2,
|
||||
assetA: 'USDT',
|
||||
assetB: 'BTC'
|
||||
baseAsset: 'USDT',
|
||||
quotedAsset: 'BTC'
|
||||
}
|
||||
|
||||
markets = new Map()
|
||||
@@ -100,31 +85,10 @@ function newDashboard () {
|
||||
}
|
||||
}
|
||||
|
||||
function userProfileChanged () {
|
||||
try {
|
||||
canvas.topSpace.initialize()
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] userProfileChanged -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
function browserResized () {
|
||||
try {
|
||||
browserCanvas = document.getElementById('canvas')
|
||||
|
||||
browserCanvas.width = window.innerWidth
|
||||
browserCanvas.height = window.innerHeight - CURRENT_TOP_MARGIN
|
||||
|
||||
viewPort.initialize()
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] browserResized -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
function setBrowserEvents () {
|
||||
window.onbeforeunload = onBrowserClosed
|
||||
function onBrowserClosed () {
|
||||
canvas.designerSpace.workspace.stopAllRunningTasks()
|
||||
// canvas.designerSpace.workspace.stopAllRunningTasks()
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -23,20 +23,23 @@ function newNodeCloning () {
|
||||
if (nodeDefinition !== undefined) {
|
||||
let object = {
|
||||
type: node.type,
|
||||
subType: node.subType,
|
||||
name: node.name,
|
||||
code: node.code
|
||||
}
|
||||
|
||||
/* Children Nodes */
|
||||
if (nodeDefinition.properties !== undefined) {
|
||||
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
|
||||
for (let i = 0; i < nodeDefinition.properties.length; i++) {
|
||||
let property = nodeDefinition.properties[i]
|
||||
|
||||
switch (property.type) {
|
||||
case 'node': {
|
||||
if (node[property.name] !== undefined) {
|
||||
object[property.name] = cloneNode(node[property.name])
|
||||
if (property.name !== previousPropertyName) {
|
||||
if (node[property.name] !== undefined) {
|
||||
object[property.name] = cloneNode(node[property.name])
|
||||
}
|
||||
previousPropertyName = property.name
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -72,20 +75,23 @@ function newNodeCloning () {
|
||||
if (nodeDefinition !== undefined) {
|
||||
let object = {
|
||||
type: node.type,
|
||||
subType: node.subType,
|
||||
name: node.name,
|
||||
code: node.code
|
||||
}
|
||||
|
||||
/* Children Nodes */
|
||||
if (nodeDefinition.properties !== undefined) {
|
||||
let previousPropertyName // Since there are cases where there are many properties with the same name,because they can hold nodes of different types but only one at the time, we have to avoind counting each property of those as individual children.
|
||||
for (let i = 0; i < nodeDefinition.properties.length; i++) {
|
||||
let property = nodeDefinition.properties[i]
|
||||
|
||||
switch (property.type) {
|
||||
case 'node': {
|
||||
if (node[property.name] !== undefined) {
|
||||
object[property.name] = redirectReferenceParents(node[property.name])
|
||||
if (property.name !== previousPropertyName) {
|
||||
if (node[property.name] !== undefined) {
|
||||
object[property.name] = redirectReferenceParents(node[property.name])
|
||||
}
|
||||
previousPropertyName = property.name
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -139,7 +145,8 @@ function newNodeCloning () {
|
||||
isPinned: node.payload.floatingObject.isPinned,
|
||||
isFrozen: (node.payload.floatingObject.isFrozen && node.payload.floatingObject.frozenManually),
|
||||
isCollapsed: (node.payload.floatingObject.isCollapsed && node.payload.floatingObject.collapsedManually),
|
||||
isTensed: (node.payload.floatingObject.isTensed && node.payload.floatingObject.tensedManually)
|
||||
angleToParent: (node.payload.floatingObject.angleToParent),
|
||||
distanceToParent: (node.payload.floatingObject.distanceToParent)
|
||||
},
|
||||
uiObject: {
|
||||
isRunning: node.payload.uiObject.isRunning,
|
||||
@@ -151,7 +158,6 @@ function newNodeCloning () {
|
||||
if (node.payload.referenceParent !== undefined) {
|
||||
savedPayload.referenceParent = {
|
||||
type: node.payload.referenceParent.type,
|
||||
subType: node.payload.referenceParent.subType,
|
||||
name: node.payload.referenceParent.name,
|
||||
id: node.payload.referenceParent.id
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -30,32 +30,45 @@ function newSessionFunctions () {
|
||||
|
||||
let key = node.name + '-' + node.type + '-' + node.id
|
||||
|
||||
let thisNodeDefinition = node.payload.referenceParent
|
||||
let lightingPath = '' +
|
||||
'Trading System->' +
|
||||
'Parameters->' +
|
||||
'Base Asset->Time Range->Time Frame->Slippage->Fee Structure->' +
|
||||
'Exchange Account Asset->Asset->' +
|
||||
'Strategy->' +
|
||||
'Trigger Stage->Trigger On Event->Trigger Off Event->Take Position Event->' +
|
||||
'Announcement->Telegram Bot->' +
|
||||
'Open Stage->Initial Definition->Open Execution->' +
|
||||
'Position Size->Position Rate->Formula->' +
|
||||
'Initial Stop->Initial Take Profit->' +
|
||||
'Manage Stage->' +
|
||||
'Stop->Take Profit->' +
|
||||
'Phase->Formula->Next Phase Event->' +
|
||||
'Situation->Condition->Javascript Code->' +
|
||||
'Announcement->Telegram Bot->' +
|
||||
'Close Stage->Close Execution->'
|
||||
|
||||
let tradingSystem = functionLibraryProtocolNode.getProtocolNode(node.payload.referenceParent, false, true, true, false, false, lightingPath)
|
||||
|
||||
lightingPath = '' +
|
||||
'Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->' +
|
||||
'Parameters->' +
|
||||
'Base Asset->Time Range->Time Frame->Slippage->Fee Structure->' +
|
||||
'Exchange Account Asset->Asset->'
|
||||
|
||||
let session = functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
|
||||
|
||||
/* Raise event to run the session */
|
||||
let event = {
|
||||
session: JSON.stringify(functionLibraryProtocolNode.getProtocolNode(node, false, true, true)),
|
||||
definition: JSON.stringify(functionLibraryProtocolNode.getProtocolNode(thisNodeDefinition, false, true, true)),
|
||||
uiCurrentValues: getUICurrentValues()
|
||||
session: JSON.stringify(session),
|
||||
tradingSystem: JSON.stringify(tradingSystem)
|
||||
}
|
||||
|
||||
systemEventHandler.raiseEvent(key, 'Run Session', event)
|
||||
|
||||
function getUICurrentValues () {
|
||||
let dateAtScreenCorner = new Date(window.localStorage.getItem('Date @ Screen Corner'))
|
||||
let currentTimePeriod = JSON.parse(window.localStorage.getItem('Current Time Period'))
|
||||
|
||||
let timePeriodsMasterArray = [marketFilesPeriods, dailyFilePeriods]
|
||||
let timePeriodArray = timePeriodsMasterArray[currentTimePeriod.filePeriodIndex]
|
||||
let timePeriod = timePeriodArray[currentTimePeriod.timePeriodIndex][1]
|
||||
|
||||
let uiCurrentValues = {
|
||||
initialDatetime: dateAtScreenCorner,
|
||||
timePeriod: timePeriod,
|
||||
timestamp: (new Date()).valueOf()
|
||||
}
|
||||
|
||||
return uiCurrentValues
|
||||
if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) {
|
||||
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -24,10 +24,42 @@ function newTaskFunctions () {
|
||||
process.payload.uiObject.run()
|
||||
}
|
||||
|
||||
let lightingPath = '->Task->' +
|
||||
'Sensor Bot Instance->' +
|
||||
'Indicator Bot Instance->' +
|
||||
'Trading Bot Instance->' +
|
||||
'Sensor Process Instance->Indicator Process Instance->Trading Process Instance->' +
|
||||
'Market Reference->' +
|
||||
'Key Instance->Exchange Account Key->' +
|
||||
'Market->Exchange Markets->Crypto Exchange->' +
|
||||
'Market Base Asset->Market Quoted Asset->Asset->' +
|
||||
'Backtesting Session->Live Trading Session->Paper Trading Session->Fordward Testing Session->' +
|
||||
'Process Definition->' +
|
||||
'Process Output->Output Dataset->Dataset Definition->Product Definition->' +
|
||||
'Process Dependencies->' +
|
||||
'Status Dependency->Status Report->Process Definition->' +
|
||||
'Data Dependency->Dataset Definition->Product Definition->' +
|
||||
'Record Definition->Record Property->Formula->' +
|
||||
'Data Building Procedure->' +
|
||||
'Procedure Initialization->Javascript Code->' +
|
||||
'Procedure Loop->Javascript Code->' +
|
||||
'Calculations Procedure->' +
|
||||
'Procedure Initialization->Javascript Code->' +
|
||||
'Procedure Loop->Javascript Code->' +
|
||||
'Status Report->' +
|
||||
'Execution Finished Event->' +
|
||||
'Execution Started Event->Execution Finished Event->Process Definition->' +
|
||||
'Sensor Bot->' +
|
||||
'Indicator Bot->' +
|
||||
'Trading Bot->' +
|
||||
'Data Mine->'
|
||||
|
||||
let definition = functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, lightingPath)
|
||||
|
||||
let event = {
|
||||
taskId: node.id,
|
||||
taskName: node.name,
|
||||
definition: JSON.stringify(functionLibraryProtocolNode.getProtocolNode(node, false, true, true, false, false, true, true)) // <- We need to do this workaround in order no to send unescaped charactars to the taskManager.
|
||||
definition: JSON.stringify(definition) // <- We need to do this workaround in order no to send unescaped charactars to the taskManager.
|
||||
}
|
||||
|
||||
if (node.payload.parentNode === undefined) {
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -13,7 +13,6 @@ function newWorkspace () {
|
||||
nodeChildren: undefined,
|
||||
getNodeThatIsOnFocus: getNodeThatIsOnFocus,
|
||||
getNodeByShortcutKey: getNodeByShortcutKey,
|
||||
getAllTradingBotInstances: getAllTradingBotInstances,
|
||||
stopAllRunningTasks: stopAllRunningTasks,
|
||||
onMenuItemClick: onMenuItemClick,
|
||||
physics: physics,
|
||||
@@ -133,19 +132,17 @@ function newWorkspace () {
|
||||
workingAtTask++
|
||||
break
|
||||
case 4:
|
||||
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode)
|
||||
functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode, true)
|
||||
workingAtTask++
|
||||
break
|
||||
case 5:
|
||||
canvas.chartSpace.finalize()
|
||||
canvas.chartSpace.reset()
|
||||
workingAtTask++
|
||||
break
|
||||
case 6:
|
||||
canvas.chartSpace.initialize()
|
||||
workingAtTask = 0
|
||||
circularProgressBar.visible = false
|
||||
break
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,34 +188,6 @@ function newWorkspace () {
|
||||
}
|
||||
}
|
||||
|
||||
function getAllTradingBotInstances () {
|
||||
let tradingBotInstances = []
|
||||
for (let i = 0; i < thisObject.workspaceNode.rootNodes.length; i++) {
|
||||
let rootNode = thisObject.workspaceNode.rootNodes[i]
|
||||
if (rootNode.type === 'Network') {
|
||||
if (rootNode.networkNodes !== undefined) {
|
||||
for (let j = 0; j < rootNode.networkNodes.length; j++) {
|
||||
let networkNode = rootNode.networkNodes[j]
|
||||
for (let i = 0; i < networkNode.taskManagers.length; i++) {
|
||||
let taskManager = networkNode.taskManagers[i]
|
||||
for (let k = 0; k < taskManager.tasks.length; k++) {
|
||||
let task = taskManager.tasks[k]
|
||||
if (task.bot !== undefined) {
|
||||
if (task.bot.type === 'Trading Bot Instance') {
|
||||
if (task.bot.payload.floatingObject.isCollapsed !== true) {
|
||||
tradingBotInstances.push(task.bot)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tradingBotInstances
|
||||
}
|
||||
|
||||
function getNodeByShortcutKey (searchingKey) {
|
||||
for (let i = 0; i < thisObject.workspaceNode.rootNodes.length; i++) {
|
||||
let rootNode = thisObject.workspaceNode.rootNodes[i]
|
||||
@@ -256,8 +225,8 @@ function newWorkspace () {
|
||||
|
||||
/* It does not exist, so we recreeate it respecting the inner state of each object. */
|
||||
let positionOffset = {
|
||||
x: spawnPosition.x - droppedNode.savedPayload.targetPosition.x,
|
||||
y: spawnPosition.y - droppedNode.savedPayload.targetPosition.y
|
||||
x: spawnPosition.x - droppedNode.savedPayload.position.x,
|
||||
y: spawnPosition.y - droppedNode.savedPayload.position.y
|
||||
}
|
||||
|
||||
thisObject.workspaceNode.rootNodes.push(droppedNode)
|
||||
@@ -277,6 +246,11 @@ function newWorkspace () {
|
||||
functionLibraryUiObjectsFromNodes.addUIObject(payload.node, relatedUiObject)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Children':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addMissingChildren(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Delete UI Object':
|
||||
{
|
||||
functionLibraryNodeDeleter.deleteUIObject(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
@@ -374,599 +348,6 @@ function newWorkspace () {
|
||||
functionLibrarySessionFunctions.stopSession(payload.node, functionLibraryProtocolNode, callBackFunction)
|
||||
}
|
||||
break
|
||||
case 'Add Definition':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addDefinition(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Team':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addTeam(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Sensor Bot':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addSensorBot(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Indicator Bot':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addIndicatorBot(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Trading Bot':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addTradingBot(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Process Definition':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addProcessDefinition(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Process Definition Items':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addMissingProcessDefinitionItems(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Product Definition Items':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addMissingProductDefinitionItems(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Process Output':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addProcessOutput(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Process Dependencies':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addProcessDependencies(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Status Report':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addStatusReport(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Execution Started Event':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addExecutionStartedEvent(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Execution Finished Event':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addExecutionFinishedEvent(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Calculations Procedure':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addCalculationsProcedure(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Data Building Procedure':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addDataBuildingProcedure(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Procedure Initialization':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addProcedureInitialization(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Procedure Loop':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addProcedureLoop(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Output Dataset':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addOutputDataset(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Status Dependency':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addStatusDependency(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Data Dependency':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addDataDependency(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Product Definition':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addProductDefinition(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Record Definition':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addRecordDefinition(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Record Property':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addRecordProperty(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Dataset Definition':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addDatasetDefinition(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Plotter':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addPlotter(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Plotter Module':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addPlotterModule(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Network':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addNetwork(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Network Node':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addNetworkNode(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Social Bots':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addSocialBots(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Telegram Bot':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addTelegramBot(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Announcement':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addAnnouncement(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Layer Manager':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addLayerManager(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Layer':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addLayer(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Task Manager':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addTaskManager(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Task':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addTask(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Sensor Bot Instance':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addSensorBotInstance(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Indicator Bot Instance':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addIndicatorBotInstance(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Trading Bot Instance':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addTradingBotInstance(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Process Instance':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addProcessInstance(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Backtesting Session':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addBacktestingSession(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Live Trading Session':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addLiveTradingSession(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Fordward Testing Session':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addFordwardTestingSession(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Paper Trading Session':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addPaperTradingSession(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Strategy':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addStrategy(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Parameters':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addParameters(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Parameters':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addMissingParameters(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Stages':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addMissingStages(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Events':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addMissingEvents(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Missing Items':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addMissingItems(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Initial Definition':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addInitialDefinition(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Open Execution':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addOpenExecution(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Close Execution':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addCloseExecution(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Phase':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addPhase(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Formula':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addFormula(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Next Phase Event':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addNextPhaseEvent(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Situation':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addSituation(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Condition':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addCondition(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Code':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addJavascriptCode(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Exchange Account':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addExchangeAccount(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Exchange Account Asset':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addExchangeAccountAsset(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Exchange Account Key':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addExchangeAccountKey(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Trading System':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addTradingSystem(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Add Personal Data':
|
||||
{
|
||||
functionLibraryUiObjectsFromNodes.addPersonalData(payload.node)
|
||||
}
|
||||
break
|
||||
case 'Delete Team': {
|
||||
functionLibraryNodeDeleter.deleteTeam(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Sensor Bot': {
|
||||
functionLibraryNodeDeleter.deleteSensorBot(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Indicator Bot': {
|
||||
functionLibraryNodeDeleter.deleteIndicatorBot(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Trading Bot': {
|
||||
functionLibraryNodeDeleter.deleteTradingBot(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Process Definition': {
|
||||
functionLibraryNodeDeleter.deleteProcessDefinition(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Process Output': {
|
||||
functionLibraryNodeDeleter.deleteProcessOutput(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Process Dependencies': {
|
||||
functionLibraryNodeDeleter.deleteProcessDependencies(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Status Report': {
|
||||
functionLibraryNodeDeleter.deleteStatusReport(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Execution Started Event': {
|
||||
functionLibraryNodeDeleter.deleteExecutionStartedEvent(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Execution Finished Event': {
|
||||
functionLibraryNodeDeleter.deleteExecutionFinishedEvent(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Calculations Procedure': {
|
||||
functionLibraryNodeDeleter.deleteCalculationsProcedure(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Data Building Procedure': {
|
||||
functionLibraryNodeDeleter.deleteDataBuildingProcedure(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Procedure Initialization': {
|
||||
functionLibraryNodeDeleter.deleteProcedureInitialization(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Procedure Loop': {
|
||||
functionLibraryNodeDeleter.deleteProcedureLoop(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Output Dataset': {
|
||||
functionLibraryNodeDeleter.deleteOutputDataset(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Status Dependency': {
|
||||
functionLibraryNodeDeleter.deleteStatusDependency(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Data Dependency': {
|
||||
functionLibraryNodeDeleter.deleteDataDependency(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Product Definition': {
|
||||
functionLibraryNodeDeleter.deleteProductDefinition(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Record Definition': {
|
||||
functionLibraryNodeDeleter.deleteRecordDefinition(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Record Property': {
|
||||
functionLibraryNodeDeleter.deleteRecordProperty(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Dataset Definition': {
|
||||
functionLibraryNodeDeleter.deleteDatasetDefinition(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Plotter': {
|
||||
functionLibraryNodeDeleter.deletePlotter(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Plotter Module': {
|
||||
functionLibraryNodeDeleter.deletePlotterModule(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Network': {
|
||||
functionLibraryNodeDeleter.deleteNetwork(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Network Node': {
|
||||
functionLibraryNodeDeleter.deleteNetworkNode(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Social Bots': {
|
||||
functionLibraryNodeDeleter.deleteSocialBots(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Social Bot': {
|
||||
functionLibraryNodeDeleter.deleteSocialBot(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Announcement': {
|
||||
functionLibraryNodeDeleter.deleteAnnouncement(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Layer Manager': {
|
||||
functionLibraryNodeDeleter.deleteLayerManager(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Layer': {
|
||||
functionLibraryNodeDeleter.deleteLayer(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Task Manager': {
|
||||
functionLibraryNodeDeleter.deleteTaskManager(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Task': {
|
||||
functionLibraryNodeDeleter.deleteTask(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Sensor Bot Instance': {
|
||||
functionLibraryNodeDeleter.deleteSensorBotInstance(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Indicator Bot Instance': {
|
||||
functionLibraryNodeDeleter.deleteIndicatorBotInstance(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Trading Bot Instance': {
|
||||
functionLibraryNodeDeleter.deleteTradingBotInstance(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Process Instance': {
|
||||
functionLibraryNodeDeleter.deleteProcessInstance(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Backtesting Session': {
|
||||
functionLibraryNodeDeleter.deleteBacktestingSession(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Live Trading Session': {
|
||||
functionLibraryNodeDeleter.deleteLiveTradingSession(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Fordward Testing Session': {
|
||||
functionLibraryNodeDeleter.deleteFordwardTestingSession(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Paper Trading Session': {
|
||||
functionLibraryNodeDeleter.deletePaperTradingSession(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Trading System': {
|
||||
functionLibraryNodeDeleter.deleteTradingSystem(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Parameters': {
|
||||
functionLibraryNodeDeleter.deleteParameters(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Base Asset': {
|
||||
functionLibraryNodeDeleter.deleteBaseAsset(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Time Range': {
|
||||
functionLibraryNodeDeleter.deleteTimeRange(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Time Period': {
|
||||
functionLibraryNodeDeleter.deleteTimePeriod(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Slippage': {
|
||||
functionLibraryNodeDeleter.deleteSlippage(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Fee Structure': {
|
||||
functionLibraryNodeDeleter.deleteFeeStructure(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Strategy': {
|
||||
functionLibraryNodeDeleter.deleteStrategy(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Trigger Stage': {
|
||||
functionLibraryNodeDeleter.deleteTriggerStage(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Open Stage': {
|
||||
functionLibraryNodeDeleter.deleteOpenStage(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Manage Stage': {
|
||||
functionLibraryNodeDeleter.deleteManageStage(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Close Stage': {
|
||||
functionLibraryNodeDeleter.deleteCloseStage(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Position Size': {
|
||||
functionLibraryNodeDeleter.deletePositionSize(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Position Rate': {
|
||||
functionLibraryNodeDeleter.deletePositionSize(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Initial Definition': {
|
||||
functionLibraryNodeDeleter.deleteInitialDefinition(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Open Execution': {
|
||||
functionLibraryNodeDeleter.deleteOpenExecution(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Close Execution': {
|
||||
functionLibraryNodeDeleter.deleteCloseExecution(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Event': {
|
||||
functionLibraryNodeDeleter.deleteEvent(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Managed Item': {
|
||||
functionLibraryNodeDeleter.deleteManagedItem(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Phase': {
|
||||
functionLibraryNodeDeleter.deletePhase(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Formula': {
|
||||
functionLibraryNodeDeleter.deleteFormula(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Situation': {
|
||||
functionLibraryNodeDeleter.deleteSituation(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Condition': {
|
||||
functionLibraryNodeDeleter.deleteCondition(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Code': {
|
||||
functionLibraryNodeDeleter.deleteJavascriptCode(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Exchange Account': {
|
||||
functionLibraryNodeDeleter.deleteExchangeAccount(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Exchange Account Asset': {
|
||||
functionLibraryNodeDeleter.deleteExchangeAccountAsset(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Exchange Account Key': {
|
||||
functionLibraryNodeDeleter.deleteExchangeAccountKey(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Personal Data': {
|
||||
functionLibraryNodeDeleter.deletePersonalData(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
case 'Delete Definition': {
|
||||
functionLibraryNodeDeleter.deleteDefinition(payload.node, thisObject.workspaceNode.rootNodes)
|
||||
break
|
||||
}
|
||||
default:
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
We call displacement to the offset we can produce to the object which the displcement object is is a child from.
|
||||
The displacement is a vector that displaces everything static drawn on on the context of the parent object.
|
||||
|
||||
*/
|
||||
|
||||
function newDisplacement () {
|
||||
let displacement = {
|
||||
containerName: '', // This is for debugging purposes only.
|
||||
parentDisplacement: undefined, // Here we store the displacement object of the parent cointainer, if exists.
|
||||
container: undefined,
|
||||
x: 0, // This is the actual x displacement.
|
||||
y: 0, // This is the actual y displacement.
|
||||
displace: displace,
|
||||
undisplaceThisPoint: undisplaceThisPoint,
|
||||
displaceThisPoint: displaceThisPoint
|
||||
}
|
||||
|
||||
return displacement
|
||||
|
||||
function displace (amountX, amountY) {
|
||||
/* First we check if by allowing this displacement we would produce the current frame to be beyond its limit. */
|
||||
|
||||
tempDisplacement = newDisplacement()
|
||||
tempDisplacement.x = amountX
|
||||
tempDisplacement.y = amountY
|
||||
|
||||
if (this.container.frame.canYouMoveHere(tempDisplacement)) {
|
||||
/* Now we displace */
|
||||
|
||||
displacement.x = displacement.x + amountX
|
||||
displacement.y = displacement.y + amountY
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function displaceThisPoint (point) {
|
||||
if (this.parentDisplacement !== undefined) {
|
||||
point = this.parentDisplacement.displaceThisPoint(point)
|
||||
}
|
||||
|
||||
point.x = point.x + displacement.x
|
||||
point.y = point.y + displacement.y
|
||||
|
||||
return point
|
||||
}
|
||||
|
||||
function undisplaceThisPoint (point) {
|
||||
if (this.parentDisplacement !== undefined) {
|
||||
point = this.parentDisplacement.undisplaceThisPoint(point)
|
||||
}
|
||||
|
||||
point.x = point.x - displacement.x
|
||||
point.y = point.y - displacement.y
|
||||
|
||||
return point
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ function newCircularMenu () {
|
||||
/* Create the array of Menu Items */
|
||||
|
||||
let iconAndTextArray = []
|
||||
let iconOnlyArray = []
|
||||
let iconOnlyArray
|
||||
let ringsArray = [[], [], []]
|
||||
|
||||
for (let i = 0; i < menuItemsInitialValues.length; i++) {
|
||||
let menuItem = newCircularMenuItem()
|
||||
@@ -81,9 +82,16 @@ function newCircularMenu () {
|
||||
menuItem.confirmationLabel = menuItemInitialValue.confirmationLabel
|
||||
menuItem.disableIfPropertyIsDefined = menuItemInitialValue.disableIfPropertyIsDefined
|
||||
menuItem.propertyToCheckFor = menuItemInitialValue.propertyToCheckFor
|
||||
menuItem.ring = menuItemInitialValue.ring
|
||||
menuItem.icons = menuItemInitialValue.icons
|
||||
|
||||
if (menuItem.label === undefined) {
|
||||
menuItem.type = 'Icon Only'
|
||||
|
||||
if (menuItem.ring === undefined) {
|
||||
menutItem.ring = 1
|
||||
}
|
||||
iconOnlyArray = ringsArray[menuItem.ring - 1]
|
||||
iconOnlyArray.push(menuItem)
|
||||
} else {
|
||||
menuItem.type = 'Icon & Text'
|
||||
@@ -95,22 +103,28 @@ function newCircularMenu () {
|
||||
menuItems.push(menuItem)
|
||||
}
|
||||
|
||||
/* Here we calculate the angles for each menu item, and then apply it if it was not previously defined. */
|
||||
let amplitud = 100
|
||||
let initialAngle = 230
|
||||
let step = amplitud / (iconOnlyArray.length - 1)
|
||||
/* There are 3 possible rings of icons, we will go through each of them here. */
|
||||
let amplitudeArray = [80, 50, 40]
|
||||
let initialAngleArray = [220, 205, 200]
|
||||
for (let j = 1; j < 4; j++) {
|
||||
let iconOnlyArray = ringsArray[j - 1]
|
||||
/* Here we calculate the angles for each menu item, and then apply it if it was not previously defined. */
|
||||
let amplitude = amplitudeArray[j - 1]
|
||||
let initialAngle = initialAngleArray[j - 1]
|
||||
let step = amplitude / (iconOnlyArray.length - 1)
|
||||
|
||||
for (let i = 0; i < iconOnlyArray.length; i++) {
|
||||
let menuItem = iconOnlyArray[i]
|
||||
let angle = initialAngle - step * i
|
||||
if (menuItem.angle === undefined) {
|
||||
menuItem.angle = angle
|
||||
for (let i = 0; i < iconOnlyArray.length; i++) {
|
||||
let menuItem = iconOnlyArray[i]
|
||||
let angle = initialAngle - step * i
|
||||
if (menuItem.angle === undefined) {
|
||||
menuItem.angle = angle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amplitud = 140
|
||||
initialAngle = -70
|
||||
step = amplitud / 7
|
||||
/* Text and Icon */
|
||||
let amplitude = 140
|
||||
let initialAngle = -70
|
||||
step = amplitude / 7
|
||||
let currentItem = (7 - iconAndTextArray.length) / 2 + 1
|
||||
for (let i = 0; i < iconAndTextArray.length; i++) {
|
||||
let menuItem = iconAndTextArray[i]
|
||||
|
||||
@@ -9,6 +9,7 @@ function newCircularMenuItem () {
|
||||
confirmationLabel: undefined,
|
||||
iconOn: undefined,
|
||||
iconOff: undefined,
|
||||
icons: undefined,
|
||||
currentIcon: undefined,
|
||||
disableIfPropertyIsDefined: undefined,
|
||||
propertyToCheckFor: undefined,
|
||||
@@ -92,6 +93,7 @@ function newCircularMenuItem () {
|
||||
thisObject.container = undefined
|
||||
thisObject.iconOn = undefined
|
||||
thisObject.iconOff = undefined
|
||||
thisObject.icons = undefined
|
||||
thisObject.currentIcon = undefined
|
||||
thisObject.payload = undefined
|
||||
thisObject.actionFunction = undefined
|
||||
@@ -110,7 +112,7 @@ function newCircularMenuItem () {
|
||||
selfMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
|
||||
if (thisObject.type === 'Icon & Text') {
|
||||
thisObject.container.frame.width = 185
|
||||
thisObject.container.frame.width = 150
|
||||
} else {
|
||||
thisObject.container.frame.width = 50
|
||||
}
|
||||
@@ -144,15 +146,28 @@ function newCircularMenuItem () {
|
||||
}
|
||||
}
|
||||
|
||||
let radiousGrowthFactor
|
||||
let radiusGrowthFactor
|
||||
if (thisObject.type === 'Icon Only') {
|
||||
radiousGrowthFactor = 5
|
||||
switch (thisObject.ring) {
|
||||
case 1: {
|
||||
radiusGrowthFactor = 5
|
||||
break
|
||||
}
|
||||
case 2: {
|
||||
radiusGrowthFactor = 3.5
|
||||
break
|
||||
}
|
||||
case 3: {
|
||||
radiusGrowthFactor = 2
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
radiousGrowthFactor = 4
|
||||
radiusGrowthFactor = 4
|
||||
}
|
||||
|
||||
thisObject.container.frame.position.x = thisObject.container.frame.radius * radiousGrowthFactor / 7 * Math.cos(toRadians(thisObject.angle)) - thisObject.currentRadius * 1.5
|
||||
thisObject.container.frame.position.y = thisObject.container.frame.radius * radiousGrowthFactor / 7 * Math.sin(toRadians(thisObject.angle)) - thisObject.container.frame.height / 2
|
||||
thisObject.container.frame.position.x = thisObject.container.frame.radius * radiusGrowthFactor / 7 * Math.cos(toRadians(thisObject.angle)) - thisObject.currentRadius * 1.5
|
||||
thisObject.container.frame.position.y = thisObject.container.frame.radius * radiusGrowthFactor / 7 * Math.sin(toRadians(thisObject.angle)) - thisObject.container.frame.height / 2
|
||||
|
||||
/* Temporary Status impacts on the label to use and the background of that label */
|
||||
if (temporaryStatusCounter > 0) {
|
||||
@@ -195,8 +210,13 @@ function newCircularMenuItem () {
|
||||
thisObject.iconOn = canvas.designerSpace.iconByUiObjectType.get(thisObject.relatedUiObject)
|
||||
thisObject.iconOff = canvas.designerSpace.iconByUiObjectType.get(thisObject.relatedUiObject)
|
||||
} else {
|
||||
thisObject.iconOn = canvas.designerSpace.iconCollection.get(thisObject.iconPathOn)
|
||||
thisObject.iconOff = canvas.designerSpace.iconCollection.get(thisObject.iconPathOff)
|
||||
if (thisObject.iconPathOn !== undefined && thisObject.iconPathOff !== undefined) {
|
||||
thisObject.iconOn = canvas.designerSpace.iconCollection.get(thisObject.iconPathOn)
|
||||
thisObject.iconOff = canvas.designerSpace.iconCollection.get(thisObject.iconPathOff)
|
||||
} else {
|
||||
thisObject.iconOn = canvas.designerSpace.iconCollection.get(thisObject.icons[thisObject.actionStatus()])
|
||||
thisObject.iconOff = canvas.designerSpace.iconCollection.get(thisObject.icons[thisObject.actionStatus()])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,7 +320,7 @@ function newCircularMenuItem () {
|
||||
}
|
||||
} else {
|
||||
if (thisObject.workFailedLabel != undefined) {
|
||||
setStatus(thisObject.workFailedLabel, UI_COLOR.TITANIUM_YELLOW, 500, STATUS_PRIMARY_WORK_FAILED)
|
||||
setStatus(thisObject.workFailedLabel, UI_COLOR.TITANIUM_YELLOW, 250, STATUS_PRIMARY_WORK_FAILED)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -311,7 +331,7 @@ function newCircularMenuItem () {
|
||||
}
|
||||
} else {
|
||||
if (thisObject.workFailedLabel != undefined) {
|
||||
setStatus(thisObject.workFailedLabel, UI_COLOR.TITANIUM_YELLOW, 500, STATUS_PRIMARY_WORK_FAILED)
|
||||
setStatus(thisObject.workFailedLabel, UI_COLOR.TITANIUM_YELLOW, 250, STATUS_PRIMARY_WORK_FAILED)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,7 +343,7 @@ function newCircularMenuItem () {
|
||||
}
|
||||
} else {
|
||||
if (thisObject.secondaryWorkFailedLabel != undefined) {
|
||||
setStatus(thisObject.secondaryWorkFailedLabel, UI_COLOR.TITANIUM_YELLOW, 500, STATUS_SECONDARY_WORK_FAILED)
|
||||
setStatus(thisObject.secondaryWorkFailedLabel, UI_COLOR.TITANIUM_YELLOW, 250, STATUS_SECONDARY_WORK_FAILED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ function newCircularProgressBar () {
|
||||
|
||||
let opacityCounters = []
|
||||
|
||||
let eventSubscriptionHeartbeat
|
||||
let eventSubscriptionIdHeartbeat
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
|
||||
systemEventHandler.stopListening(key, eventSubscriptionHeartbeat)
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdHeartbeat)
|
||||
|
||||
thisObject.container = undefined
|
||||
thisObject.payload = undefined
|
||||
@@ -52,6 +52,8 @@ function newCircularProgressBar () {
|
||||
}
|
||||
|
||||
function onHeartBeat (message) {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
if (thisObject.payload.uiObject === undefined) { return }
|
||||
opacityCounters[message.event.seconds] = 2000
|
||||
thisObject.payload.uiObject.setValue(message.event.processingDate)
|
||||
}
|
||||
@@ -76,11 +78,11 @@ function newCircularProgressBar () {
|
||||
}
|
||||
}
|
||||
|
||||
function drawBackground (pFloatingObject) {
|
||||
function drawForeground (pFloatingObject) {
|
||||
|
||||
}
|
||||
|
||||
function drawForeground (pFloatingObject) {
|
||||
function drawBackground (pFloatingObject) {
|
||||
const VISIBLE_RADIUS = thisObject.container.frame.radius * 2
|
||||
|
||||
let visiblePosition = {
|
||||
@@ -104,12 +106,12 @@ function newCircularProgressBar () {
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GOLDEN_ORANGE + ', ' + OPACITY * 2 + ')'
|
||||
browserCanvasContext.lineWidth = 6 + opacityCounters[i] / 100
|
||||
browserCanvasContext.lineWidth = 6 + opacityCounters[i] / 100 / 2
|
||||
browserCanvasContext.setLineDash([3, 4])
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK_TURQUOISE + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = 0 + opacityCounters[i] / 100
|
||||
browserCanvasContext.lineWidth = 0 + opacityCounters[i] / 100 / 2
|
||||
browserCanvasContext.setLineDash([3, 4])
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ function newConfigEditor () {
|
||||
thisObject.container.frame.position.y = 0
|
||||
|
||||
let isMouseOver = false
|
||||
let SIZE_FACTOR = 0.6
|
||||
|
||||
return thisObject
|
||||
|
||||
@@ -135,8 +136,8 @@ function newConfigEditor () {
|
||||
thisObject.container.frame.position.x = 0
|
||||
thisObject.container.frame.position.y = 0
|
||||
|
||||
thisObject.container.frame.width = thisObject.container.frame.radius * 1.8 * 2
|
||||
thisObject.container.frame.height = thisObject.container.frame.radius * 1 * 2
|
||||
thisObject.container.frame.width = thisObject.container.frame.radius * 1.8 * SIZE_FACTOR
|
||||
thisObject.container.frame.height = thisObject.container.frame.radius * 1 * SIZE_FACTOR
|
||||
|
||||
let textAreaPosition = {
|
||||
x: 0 - thisObject.container.frame.width / 2,
|
||||
@@ -168,7 +169,7 @@ function newConfigEditor () {
|
||||
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
let radius = thisObject.container.frame.radius * 2
|
||||
let radius = thisObject.container.frame.radius * SIZE_FACTOR
|
||||
|
||||
if (radius > 0.5) {
|
||||
browserCanvasContext.beginPath()
|
||||
|
||||
@@ -263,7 +263,9 @@ function newFloatingLayer () {
|
||||
|
||||
for (let i = 0; i < visibleFloatingObjects.length; i++) {
|
||||
let floatingObject = visibleFloatingObjects[i]
|
||||
floatingObject.physics()
|
||||
|
||||
/* From here on, only if they are not too far. */
|
||||
if (canvas.floatingSpace.isItFar(floatingObject.payload)) { continue }
|
||||
|
||||
if (floatingObject.positionLocked === false) {
|
||||
@@ -286,18 +288,6 @@ function newFloatingLayer () {
|
||||
}
|
||||
|
||||
switch (floatingObject.type) {
|
||||
|
||||
case 'Profile Ball': {
|
||||
payload.targetPosition = floatingObject.payload.profile.position
|
||||
payload.visible = floatingObject.payload.profile.visible
|
||||
break
|
||||
}
|
||||
case 'Note': {
|
||||
payload.targetPosition = floatingObject.payload.notes[floatingObject.payloadNoteIndex].position
|
||||
payload.visible = floatingObject.payload.notes[floatingObject.payloadNoteIndex].visible
|
||||
|
||||
break
|
||||
}
|
||||
case 'UI Object': {
|
||||
payload.targetPosition = floatingObject.payload.targetPosition
|
||||
payload.visible = floatingObject.payload.visible
|
||||
@@ -341,8 +331,6 @@ function newFloatingLayer () {
|
||||
// We let the Floating Object animate the physics loops by itself.
|
||||
checkBoundaries(floatingObject)
|
||||
|
||||
floatingObject.physics()
|
||||
|
||||
/* Collision Control */
|
||||
|
||||
for (let k = i + 1; k < visibleFloatingObjects.length; k++) {
|
||||
@@ -559,15 +547,6 @@ function newFloatingLayer () {
|
||||
}
|
||||
|
||||
switch (floatingObject2.type) {
|
||||
|
||||
case 'Profile Ball': {
|
||||
payload.targetPosition = floatingObject2.payload.profile.position
|
||||
break
|
||||
}
|
||||
case 'Note': {
|
||||
payload.targetPosition = floatingObject2.payload.notes[floatingObject2.payloadNoteIndex].position
|
||||
break
|
||||
}
|
||||
case 'UI Object': {
|
||||
payload.targetPosition = floatingObject2.payload.targetPosition
|
||||
break
|
||||
|
||||
+113
-28
@@ -22,7 +22,8 @@ function newFloatingObject () {
|
||||
targetRadius: 0, // This is the target radius of the floating object with zoom applied. It should be animated until reaching this value.
|
||||
isPinned: false,
|
||||
isFrozen: false,
|
||||
isTensed: false,
|
||||
angleToParent: ANGLE_TO_PARENT.RANGE_90,
|
||||
distanceToParent: DISTANCE_TO_PARENT.PARENT_100X,
|
||||
isCollapsed: false,
|
||||
isParentCollapsed: false,
|
||||
frozenManually: false,
|
||||
@@ -30,13 +31,15 @@ function newFloatingObject () {
|
||||
getPinStatus: getPinStatus,
|
||||
getFreezeStatus: getFreezeStatus,
|
||||
getCollapseStatus: getCollapseStatus,
|
||||
getTensionStatus: getTensionStatus,
|
||||
getAngleToParent: getAngleToParent,
|
||||
getDistanceToParent: getDistanceToParent,
|
||||
nearbyFloatingObjects: [],
|
||||
setPosition: setPosition,
|
||||
pinToggle: pinToggle,
|
||||
freezeToggle: freezeToggle,
|
||||
collapseToggle: collapseToggle,
|
||||
tensionToggle: tensionToggle,
|
||||
angleToParentToggle: angleToParentToggle,
|
||||
distanceToParentToggle: distanceToParentToggle,
|
||||
physics: physics,
|
||||
initializeMass: initializeMass,
|
||||
initializeRadius: initializeRadius,
|
||||
@@ -138,8 +141,12 @@ function newFloatingObject () {
|
||||
return thisObject.isCollapsed
|
||||
}
|
||||
|
||||
function getTensionStatus () {
|
||||
return thisObject.isTensed
|
||||
function getAngleToParent () {
|
||||
return thisObject.angleToParent
|
||||
}
|
||||
|
||||
function getDistanceToParent () {
|
||||
return thisObject.distanceToParent
|
||||
}
|
||||
|
||||
function freezeToggle () {
|
||||
@@ -164,32 +171,73 @@ function newFloatingObject () {
|
||||
return thisObject.isCollapsed
|
||||
}
|
||||
|
||||
function tensionToggle () {
|
||||
if (thisObject.isTensed !== true) {
|
||||
thisObject.isTensed = true
|
||||
thisObject.tensedManually = true
|
||||
} else {
|
||||
thisObject.isTensed = false
|
||||
thisObject.tensedManually = false
|
||||
function angleToParentToggle () {
|
||||
switch (thisObject.angleToParent) {
|
||||
case ANGLE_TO_PARENT.NOT_FIXED:
|
||||
thisObject.angleToParent = ANGLE_TO_PARENT.RANGE_360
|
||||
break
|
||||
case ANGLE_TO_PARENT.RANGE_360:
|
||||
thisObject.angleToParent = ANGLE_TO_PARENT.RANGE_180
|
||||
break
|
||||
case ANGLE_TO_PARENT.RANGE_180:
|
||||
thisObject.angleToParent = ANGLE_TO_PARENT.RANGE_90
|
||||
break
|
||||
case ANGLE_TO_PARENT.RANGE_90:
|
||||
thisObject.angleToParent = ANGLE_TO_PARENT.RANGE_45
|
||||
break
|
||||
case ANGLE_TO_PARENT.RANGE_45:
|
||||
thisObject.angleToParent = ANGLE_TO_PARENT.NOT_FIXED
|
||||
break
|
||||
}
|
||||
return thisObject.isTensed
|
||||
|
||||
return thisObject.angleToParent
|
||||
}
|
||||
|
||||
function distanceToParentToggle () {
|
||||
switch (thisObject.distanceToParent) {
|
||||
case DISTANCE_TO_PARENT.NOT_FIXED:
|
||||
thisObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_025X
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_025X:
|
||||
thisObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_050X
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_050X:
|
||||
thisObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_100X
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_100X:
|
||||
thisObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_150X
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_150X:
|
||||
thisObject.distanceToParent = DISTANCE_TO_PARENT.PARENT_200X
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_200X:
|
||||
thisObject.distanceToParent = DISTANCE_TO_PARENT.NOT_FIXED
|
||||
break
|
||||
}
|
||||
|
||||
return thisObject.distanceToParent
|
||||
}
|
||||
|
||||
function physics () {
|
||||
collapsePhysics()
|
||||
frozenPhysics()
|
||||
/* From here on, only if they are not too far. */
|
||||
if (canvas.floatingSpace.isItFar(thisObject.payload)) { return }
|
||||
thisObjectPhysics()
|
||||
thisObject.payload.uiObject.physics()
|
||||
frozenPhysics()
|
||||
tensionPhysics()
|
||||
positionContraintsPhysics()
|
||||
}
|
||||
|
||||
function frozenPhysics () {
|
||||
if (thisObject.frozenManually !== false) { return }
|
||||
if (thisObject.payload === undefined) { return }
|
||||
let parent = thisObject.payload.chainParent
|
||||
if (parent !== undefined && parent.payload !== undefined) {
|
||||
thisObject.isFrozen = parent.payload.floatingObject.isFrozen
|
||||
if (parent !== undefined) {
|
||||
if (parent.payload !== undefined) {
|
||||
if (parent.payload.floatingObject !== undefined) {
|
||||
thisObject.isFrozen = parent.payload.floatingObject.isFrozen
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,20 +253,54 @@ function newFloatingObject () {
|
||||
}
|
||||
}
|
||||
|
||||
function tensionPhysics () {
|
||||
/* Tension Effect */
|
||||
|
||||
if (thisObject.isTensed === true) {
|
||||
function positionContraintsPhysics () {
|
||||
if (thisObject.angleToParent !== ANGLE_TO_PARENT.NOT_FIXED && thisObject.isOnFocus !== true) {
|
||||
let parent = thisObject.payload.chainParent
|
||||
if (parent === undefined) { return }
|
||||
if (parent.payload === undefined) { return }
|
||||
if (parent.payload.position === undefined) { return }
|
||||
|
||||
let distanceToChainParent = Math.sqrt(Math.pow(parent.payload.position.x - thisObject.container.frame.position.x, 2) + Math.pow(parent.payload.position.y - thisObject.container.frame.position.y, 2)) // ... we calculate the distance ...
|
||||
let distanceToParent = Math.sqrt(Math.pow(parent.payload.position.x - thisObject.container.frame.position.x, 2) + Math.pow(parent.payload.position.y - thisObject.container.frame.position.y, 2)) // ... we calculate the distance ...
|
||||
let parentChildren = canvas.designerSpace.workspace.nodeChildren.childrenCount(parent, thisObject.payload.node)
|
||||
let axisCount = parentChildren.childrenCount
|
||||
let axisIndex = parentChildren.childIndex
|
||||
let baseAngle = 0
|
||||
let angleToParentAngle
|
||||
|
||||
if (parent.payload.distance !== undefined) {
|
||||
switch (thisObject.distanceToParent) {
|
||||
case DISTANCE_TO_PARENT.PARENT_025X:
|
||||
distanceToParent = parent.payload.distance / 4
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_050X:
|
||||
distanceToParent = parent.payload.distance / 2
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_100X:
|
||||
distanceToParent = parent.payload.distance
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_150X:
|
||||
distanceToParent = parent.payload.distance * 1.5
|
||||
break
|
||||
case DISTANCE_TO_PARENT.PARENT_200X:
|
||||
distanceToParent = parent.payload.distance * 2
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
switch (thisObject.angleToParent) {
|
||||
case ANGLE_TO_PARENT.RANGE_360:
|
||||
angleToParentAngle = 360
|
||||
break
|
||||
case ANGLE_TO_PARENT.RANGE_180:
|
||||
angleToParentAngle = 180
|
||||
break
|
||||
case ANGLE_TO_PARENT.RANGE_90:
|
||||
angleToParentAngle = 90
|
||||
break
|
||||
case ANGLE_TO_PARENT.RANGE_45:
|
||||
angleToParentAngle = 45
|
||||
break
|
||||
}
|
||||
|
||||
if (axisIndex === undefined) {
|
||||
axisCount = 1
|
||||
@@ -238,18 +320,21 @@ function newFloatingObject () {
|
||||
}
|
||||
}
|
||||
|
||||
let angleStep = 360 / axisCount
|
||||
let separatorAngle = (360 - angleToParentAngle) / 2
|
||||
let angleStep = angleToParentAngle / axisCount
|
||||
|
||||
thisObject.payload.angle = baseAngle + (axisIndex - 1) * angleStep
|
||||
thisObject.payload.angle = baseAngle + separatorAngle + (axisIndex - 1) * angleStep
|
||||
if (thisObject.payload.angle >= 360) {
|
||||
thisObject.payload.angle = thisObject.payload.angle - 360
|
||||
}
|
||||
|
||||
if (distanceToChainParent > 2000) { return } // this is introduced to avoid edges cases when importing workspaces.
|
||||
thisObject.payload.distance = distanceToParent
|
||||
|
||||
if (distanceToParent > 2000 || thisObject.isPinned === true) { return } // this is introduced to avoid edges cases when importing workspaces.
|
||||
|
||||
newPosition = {
|
||||
x: parent.payload.position.x + distanceToChainParent * Math.cos(toRadians(thisObject.payload.angle)),
|
||||
y: parent.payload.position.y + distanceToChainParent * Math.sin(toRadians(thisObject.payload.angle))
|
||||
x: parent.payload.position.x + distanceToParent * Math.cos(toRadians(thisObject.payload.angle)),
|
||||
y: parent.payload.position.y + distanceToParent * Math.sin(toRadians(thisObject.payload.angle))
|
||||
}
|
||||
if (isNaN(newPosition.x) === false) {
|
||||
thisObject.container.frame.position.x = newPosition.x
|
||||
@@ -330,6 +415,7 @@ function newFloatingObject () {
|
||||
}
|
||||
|
||||
function removeFocus () {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
if (thisObject.isOnFocus === true) {
|
||||
thisObject.targetRadius = thisObject.rawRadius * 1
|
||||
thisObject.targetImageSize = thisObject.rawImageSize * 1
|
||||
@@ -478,4 +564,3 @@ function newFloatingObject () {
|
||||
function updateRadius () {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,334 +0,0 @@
|
||||
|
||||
function newNote () {
|
||||
const MODULE_NAME = 'Note'
|
||||
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
physics: physics,
|
||||
drawBackground: drawBackground,
|
||||
drawMiddleground: drawMiddleground,
|
||||
drawForeground: drawForeground,
|
||||
drawOnFocus: drawOnFocus,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize
|
||||
}
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME, 'Circle')
|
||||
thisObject.container.isClickeable = false
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.frame.radius = 0
|
||||
thisObject.container.frame.position.x = 0
|
||||
thisObject.container.frame.position.y = 0
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
let container
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
|
||||
}
|
||||
|
||||
function onMouseOver () {
|
||||
|
||||
}
|
||||
|
||||
function onMouseNotOver () {
|
||||
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
pPoint = event.point
|
||||
pFloatingObject = event.parent
|
||||
}
|
||||
|
||||
function drawBackground (pFloatingObject) {
|
||||
let point = {
|
||||
x: pFloatingObject.payload.notes[pFloatingObject.payloadNoteIndex].position.x,
|
||||
y: pFloatingObject.payload.notes[pFloatingObject.payloadNoteIndex].position.y
|
||||
}
|
||||
|
||||
point = viewPort.fitIntoVisibleArea(point)
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 1) {
|
||||
/* Target Line */
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(pFloatingObject.container.frame.position.x, pFloatingObject.container.frame.position.y)
|
||||
browserCanvasContext.lineTo(point.x, point.y)
|
||||
browserCanvasContext.strokeStyle = 'rgba(204, 204, 204, 0.5)'
|
||||
browserCanvasContext.setLineDash([4, 2])
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.stroke()
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
}
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 0.5) {
|
||||
/* Target Spot */
|
||||
|
||||
var radius = 1
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(point.x, point.y, radius, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.fillStyle = 'rgba(30, 30, 30, 1)'
|
||||
browserCanvasContext.fill()
|
||||
}
|
||||
}
|
||||
|
||||
function drawOnFocus () {
|
||||
|
||||
}
|
||||
|
||||
function drawMiddleground () {
|
||||
|
||||
}
|
||||
|
||||
function drawForeground (pFloatingObject) {
|
||||
const BUBBLE_CORNERS_RADIUS = 5
|
||||
const TITLE_BAR_HEIGHT = 14
|
||||
|
||||
const BUBBLE_WIDTH = BUBBLE_CORNERS_RADIUS + pFloatingObject.container.frame.radius * 4
|
||||
const BUBBLE_HEIGHT = BUBBLE_CORNERS_RADIUS + pFloatingObject.container.frame.radius * 2
|
||||
|
||||
let borderPoint1
|
||||
let borderPoint2
|
||||
let borderPoint3
|
||||
let borderPoint4
|
||||
|
||||
let intialDisplace = {
|
||||
x: pFloatingObject.container.frame.position.x - BUBBLE_WIDTH / 2,
|
||||
y: pFloatingObject.container.frame.position.y - BUBBLE_HEIGHT / 2
|
||||
}
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 5) {
|
||||
/* Rounded Background */
|
||||
|
||||
borderPoint1 = {
|
||||
x: intialDisplace.x + BUBBLE_CORNERS_RADIUS,
|
||||
y: intialDisplace.y + BUBBLE_CORNERS_RADIUS
|
||||
}
|
||||
|
||||
borderPoint2 = {
|
||||
x: intialDisplace.x + BUBBLE_WIDTH - BUBBLE_CORNERS_RADIUS,
|
||||
y: intialDisplace.y + BUBBLE_CORNERS_RADIUS
|
||||
}
|
||||
|
||||
borderPoint3 = {
|
||||
x: intialDisplace.x + BUBBLE_WIDTH - BUBBLE_CORNERS_RADIUS,
|
||||
y: intialDisplace.y + BUBBLE_HEIGHT - BUBBLE_CORNERS_RADIUS
|
||||
}
|
||||
|
||||
borderPoint4 = {
|
||||
x: intialDisplace.x + BUBBLE_CORNERS_RADIUS,
|
||||
y: intialDisplace.y + +BUBBLE_HEIGHT - BUBBLE_CORNERS_RADIUS
|
||||
}
|
||||
|
||||
titleBarPoint1 = {
|
||||
x: intialDisplace.x + 0,
|
||||
y: intialDisplace.y + TITLE_BAR_HEIGHT
|
||||
}
|
||||
|
||||
titleBarPoint2 = {
|
||||
x: intialDisplace.x + BUBBLE_WIDTH,
|
||||
y: intialDisplace.y + TITLE_BAR_HEIGHT
|
||||
}
|
||||
|
||||
/* We paint the panel background first */
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(255, 249, 196, 0.75)'
|
||||
browserCanvasContext.beginPath()
|
||||
|
||||
browserCanvasContext.arc(borderPoint1.x, borderPoint1.y, BUBBLE_CORNERS_RADIUS, 1.0 * Math.PI, 1.5 * Math.PI)
|
||||
browserCanvasContext.lineTo(borderPoint2.x, borderPoint2.y - BUBBLE_CORNERS_RADIUS)
|
||||
browserCanvasContext.arc(borderPoint2.x, borderPoint2.y, BUBBLE_CORNERS_RADIUS, 1.5 * Math.PI, 2.0 * Math.PI)
|
||||
browserCanvasContext.lineTo(borderPoint3.x + BUBBLE_CORNERS_RADIUS, borderPoint3.y)
|
||||
browserCanvasContext.arc(borderPoint3.x, borderPoint3.y, BUBBLE_CORNERS_RADIUS, 0 * Math.PI, 0.5 * Math.PI)
|
||||
browserCanvasContext.lineTo(borderPoint4.x, borderPoint4.y + BUBBLE_CORNERS_RADIUS)
|
||||
browserCanvasContext.arc(borderPoint4.x, borderPoint4.y, BUBBLE_CORNERS_RADIUS, 0.5 * Math.PI, 1.0 * Math.PI)
|
||||
browserCanvasContext.lineTo(borderPoint1.x - BUBBLE_CORNERS_RADIUS, borderPoint1.y)
|
||||
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fill()
|
||||
|
||||
browserCanvasContext.lineWidth = 0.1
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.DARK + ', 0.75)'
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
/* We paint the title bar now */
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(244, 224, 44, 0.75)'
|
||||
browserCanvasContext.beginPath()
|
||||
|
||||
browserCanvasContext.moveTo(titleBarPoint1.x, titleBarPoint1.y)
|
||||
browserCanvasContext.lineTo(borderPoint1.x - BUBBLE_CORNERS_RADIUS, borderPoint1.y)
|
||||
browserCanvasContext.arc(borderPoint1.x, borderPoint1.y, BUBBLE_CORNERS_RADIUS, 1.0 * Math.PI, 1.5 * Math.PI)
|
||||
browserCanvasContext.lineTo(borderPoint2.x, borderPoint2.y - BUBBLE_CORNERS_RADIUS)
|
||||
browserCanvasContext.arc(borderPoint2.x, borderPoint2.y, BUBBLE_CORNERS_RADIUS, 1.5 * Math.PI, 2.0 * Math.PI)
|
||||
browserCanvasContext.lineTo(titleBarPoint2.x, titleBarPoint2.y)
|
||||
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.fill()
|
||||
|
||||
browserCanvasContext.lineWidth = 0.1
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', 0.75)'
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 0.5) {
|
||||
/* Image */
|
||||
|
||||
let imagePosition = {
|
||||
x: pFloatingObject.container.frame.position.x,
|
||||
y: pFloatingObject.container.frame.position.y + BUBBLE_HEIGHT / 2
|
||||
}
|
||||
|
||||
if (pFloatingObject.payloadImageId !== undefined) {
|
||||
let image = document.getElementById(pFloatingObject.payloadImageId)
|
||||
|
||||
if (image !== null) {
|
||||
browserCanvasContext.drawImage(image, imagePosition.x - pFloatingObject.currentImageSize / 2, imagePosition.y - pFloatingObject.currentImageSize / 2, pFloatingObject.currentImageSize, pFloatingObject.currentImageSize)
|
||||
}
|
||||
}
|
||||
|
||||
/* Image Contourn */
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(imagePosition.x, imagePosition.y, pFloatingObject.currentImageSize / 2, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(30, 30, 30, 0.25)'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
/* Labels */
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 6) {
|
||||
browserCanvasContext.strokeStyle = pFloatingObject.labelStrokeStyle
|
||||
|
||||
const SIZE_PERCENTAGE = Math.trunc(pFloatingObject.container.frame.radius / pFloatingObject.targetRadius * 100) / 100
|
||||
let ALPHA
|
||||
|
||||
if (pFloatingObject.targetRadius > 0) {
|
||||
ALPHA = 0.5 - (1 - SIZE_PERCENTAGE) * 5
|
||||
} else {
|
||||
// Object is dying...
|
||||
|
||||
ALPHA = Math.trunc((0.5 - (100 - pFloatingObject.container.frame.radius / 100)) * 100) / 100
|
||||
|
||||
if (ALPHA < 0) { ALPHA = 0 }
|
||||
}
|
||||
|
||||
let labelPoint
|
||||
let fontSize = 10
|
||||
|
||||
let label
|
||||
|
||||
/* print the title */
|
||||
|
||||
label = pFloatingObject.payload.notes[pFloatingObject.payloadNoteIndex].title
|
||||
|
||||
if (label !== undefined) {
|
||||
if (SIZE_PERCENTAGE > 0.9) {
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
|
||||
let xOffset = label.length / 2 * fontSize * FONT_ASPECT_RATIO
|
||||
let yOffset = (TITLE_BAR_HEIGHT - fontSize) / 2 + 2
|
||||
|
||||
labelPoint = {
|
||||
x: intialDisplace.x + BUBBLE_WIDTH / 2 - xOffset,
|
||||
y: intialDisplace.y + TITLE_BAR_HEIGHT - yOffset
|
||||
}
|
||||
|
||||
browserCanvasContext.fillStyle = 'rgba(30, 30, 30, ' + ALPHA + ')'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
}
|
||||
|
||||
/* Message Body */
|
||||
|
||||
label = pFloatingObject.payload.notes[pFloatingObject.payloadNoteIndex].body
|
||||
|
||||
if (label !== undefined) {
|
||||
const WORDS_PER_ROW = 5
|
||||
const TOTAL_ROWS = 5
|
||||
|
||||
if (SIZE_PERCENTAGE > 0.9) {
|
||||
let rawLabelArray = label.split(' ')
|
||||
let labelArray = []
|
||||
|
||||
/* Lets check when words are to long we add an empty space to the same line so as to roll all other words forward. */
|
||||
|
||||
for (let i = 0; i < rawLabelArray.length; i++) {
|
||||
let word = rawLabelArray[i]
|
||||
|
||||
labelArray.push(word)
|
||||
|
||||
if (word.length > 8) {
|
||||
labelArray.push('')
|
||||
}
|
||||
|
||||
if (word.length > 10) {
|
||||
labelArray.push('')
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate each ROW */
|
||||
|
||||
let labelRows = []
|
||||
|
||||
for (let i = 0; i < TOTAL_ROWS; i++) {
|
||||
let labelRow = ''
|
||||
|
||||
for (let j = 0; j < WORDS_PER_ROW; j++) {
|
||||
let newWord = labelArray[j + i * WORDS_PER_ROW]
|
||||
|
||||
if (newWord !== undefined && newWord !== '') {
|
||||
labelRow = labelRow + ' ' + newWord
|
||||
}
|
||||
}
|
||||
|
||||
if (labelRow !== '') {
|
||||
labelRows.push(labelRow)
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we plot each row. */
|
||||
|
||||
for (let i = 0; i < labelRows.length; i++) {
|
||||
let labelRow = labelRows[i]
|
||||
|
||||
let startingPosition = {
|
||||
x: pFloatingObject.container.frame.position.x,
|
||||
y: pFloatingObject.container.frame.position.y - labelRows.length / 2 * (fontSize * FONT_ASPECT_RATIO + 10)
|
||||
}
|
||||
|
||||
labelPoint = {
|
||||
x: startingPosition.x - labelRow.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: startingPosition.y + (i + 1) * (fontSize * FONT_ASPECT_RATIO + 10)
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(60, 60, 60, ' + ALPHA + ')'
|
||||
browserCanvasContext.fillText(labelRow, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,314 +0,0 @@
|
||||
|
||||
function newNoteSets () {
|
||||
/*
|
||||
Different plotters will identify sets of notes whithin the data they are plotting. They will create with them arrays of Notes data.
|
||||
On the other hand the floating space, and a floting layer in particular, manages Notes floating objects, which are visible entities
|
||||
that floats on the screen. These entities are animated at a certain peace, and their life cycle differs from the life cycle of the
|
||||
arrays of raw data plotters have.
|
||||
|
||||
The purpose of this module, is to provide a mechnism of syncronization between the raw data and the visible floating objects and a
|
||||
data structure wheere to store these floating objects.
|
||||
|
||||
A NoteSet in this context is an array of Notes floating objects belonging to the same owner, which could be a certain bot for instance.
|
||||
This module is capable of managing an array of NoteSets.
|
||||
*/
|
||||
|
||||
const MODULE_NAME = 'Note Sets'
|
||||
const INFO_LOG = false
|
||||
const INFO_WARN = true
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let thisObject = {
|
||||
createNoteSet: createNoteSet,
|
||||
destroyNoteSet: destroyNoteSet,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let noteSets = []
|
||||
let floatingLayer
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize (pFloatingLayer) {
|
||||
floatingLayer = pFloatingLayer
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
floatingLayer.finalize()
|
||||
floatingLayer = undefined
|
||||
}
|
||||
|
||||
function createNoteSet (pPayload, pEventHandler, callBackFunction) {
|
||||
try {
|
||||
/*
|
||||
During the creating of a NoteSet, no floating objects are created yet. What we do here is to create the data structure which will allocate
|
||||
the Notes floating objects, once we receive the array of notes raw data from the plotter. This array will come as an event raised by the
|
||||
plotter everytime it's set of raw data changes. Remember that the plotter is not only filtering out notes based on how far they are from the
|
||||
position the user gives to the viewport, but also, the plotter can be receiving actually new notes from its datasource.
|
||||
*/
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> Entering function.') }
|
||||
|
||||
let noteSet = {
|
||||
imageId: pPayload.profile.imageId,
|
||||
floatingNotes: [],
|
||||
payload: pPayload,
|
||||
handle: Math.floor((Math.random() * 10000000) + 1)
|
||||
}
|
||||
|
||||
noteSets.push(noteSet)
|
||||
|
||||
pEventHandler.listenToEvent('Notes Changed', onNotesChanged, noteSets.length - 1)
|
||||
|
||||
callBackFunction(GLOBAL.CUSTOM_OK_RESPONSE, noteSet.handle)
|
||||
|
||||
function onNotesChanged (pNewNotes, pNoteSetIndex) {
|
||||
try {
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Entering function.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> pNewNotes.length = ' + pNewNotes.length) }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> pNoteSetIndex = ' + pNoteSetIndex) }
|
||||
|
||||
let noteSet = noteSets[pNoteSetIndex]
|
||||
let found = false
|
||||
let newFloatingNotes
|
||||
|
||||
/*
|
||||
First we remove the old notes. This means that we are going to scan all the floating objects that we have, and see one by one if they
|
||||
are still present on the raw data sent by the plotter. If it is not there, that means that the floating object must be discarded.
|
||||
*/
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes.') }
|
||||
|
||||
newFloatingNotes = [] // We will create a new array of Floating Notes as a result of this operation.
|
||||
|
||||
/*
|
||||
Here we scan the curren array of floating objects. We use the date + rate to create a unique key for each one, in order to be able to
|
||||
compare it with the raw data. You will notice that instead of deleting from the current array what we actually do is to add the ones
|
||||
that are still at the raw data array to a new array, and not adding the ones that are not.
|
||||
*/
|
||||
|
||||
for (let j = 0; j < noteSet.floatingNotes.length; j++) {
|
||||
found = false
|
||||
|
||||
let floatingNote = noteSet.floatingNotes[j]
|
||||
let floatingNoteKey = floatingNote.date.toString() + floatingNote.rate.toString()
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> j = ' + j) }
|
||||
|
||||
let i
|
||||
|
||||
for (let i = 0; i < pNewNotes.length; i++) {
|
||||
let plotterNote = pNewNotes[i]
|
||||
let plotterNoteKey = plotterNote.date.toString() + plotterNote.rate.toString()
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> i = ' + i) }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> floatingNoteKey = ' + floatingNoteKey) }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> plotterNoteKey = ' + plotterNoteKey) }
|
||||
|
||||
if (plotterNoteKey === floatingNoteKey) {
|
||||
found = true
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> found = ' + found) }
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> End of For i.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> found = ' + found) }
|
||||
|
||||
if (found === false) {
|
||||
/*
|
||||
Each time we identify a floatingObject that is not at the raw data anymore, we request the floatinglayer to kill it.
|
||||
*/
|
||||
|
||||
floatingLayer.removeFloatingObject(floatingNote.floatingHandle)
|
||||
} else {
|
||||
newFloatingNotes.push(floatingNote)
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> floatingNote.floatingHandle = ' + floatingNote.floatingHandle) }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> Added to newFloatingNotes.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> newFloatingNotes.length = ' + newFloatingNotes.length) }
|
||||
|
||||
/*
|
||||
We set a property at each floatingObject of which is the index of the note at the raw data array, so that it can later evaluate its position or its visibility.
|
||||
*/
|
||||
|
||||
let floatingObject = floatingLayer.getFloatingObject(floatingNote.floatingHandle)
|
||||
floatingObject.payloadNoteIndex = i
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> floatingObject index updated.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> floatingObject.payloadNoteIndex = ' + i) }
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
We replace the current array, with the new one that only contains the surviving floating objects, meaning the ones that are still at the raw data received.
|
||||
*/
|
||||
|
||||
noteSet.floatingNotes = newFloatingNotes
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Remove old Notes -> noteSet.floatingNotes.length = ' + noteSet.floatingNotes.length) }
|
||||
|
||||
/*
|
||||
Second we add the new notes. There might be new notes at the raw data received that we didnt have before at the NodeSet array. To figure out which
|
||||
ones are, we need to scan the raw data array and compare each element with the ones of the NodeSet array. Whenever we find one that is not there,
|
||||
we add it.
|
||||
*/
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes.') }
|
||||
|
||||
newFloatingNotes = [] // We will create a new array of Floating Notes as a result of this operation.
|
||||
|
||||
/*
|
||||
We are using the date and rate as a unique key to identify each note. To prevent the cases of duplicate keys, we will check that at
|
||||
least to consecutive records dont have the same key, and if they do, will ignore the second one.
|
||||
*/
|
||||
|
||||
let lastPlotterKey = ''
|
||||
|
||||
for (let i = 0; i < pNewNotes.length; i++) {
|
||||
found = false
|
||||
|
||||
let plotterNote = pNewNotes[i]
|
||||
let plotterNoteKey = plotterNote.date.toString() + plotterNote.rate.toString()
|
||||
let floatingNote
|
||||
let floatingNoteKey
|
||||
|
||||
if (lastPlotterKey === plotterNoteKey) {
|
||||
if (INFO_WARN === true) { logger.write('[WARN] createNoteSet -> onNotesChanged -> Add new Notes -> Duplicate record detected. Discarding it.') }
|
||||
if (INFO_WARN === true) { logger.write('[WARN] createNoteSet -> onNotesChanged -> Add new Notes -> i = ' + i) }
|
||||
continue
|
||||
}
|
||||
|
||||
lastPlotterKey = plotterNoteKey
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> i = ' + i) }
|
||||
|
||||
for (let j = 0; j < noteSet.floatingNotes.length; j++) {
|
||||
floatingNote = noteSet.floatingNotes[j]
|
||||
floatingNoteKey = floatingNote.date.toString() + floatingNote.rate.toString()
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> j = ' + j) }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> floatingNoteKey = ' + floatingNoteKey) }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> plotterNoteKey = ' + plotterNoteKey) }
|
||||
|
||||
if (plotterNoteKey === floatingNoteKey) {
|
||||
found = true
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> found = ' + found) }
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> End of For j.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> found = ' + found) }
|
||||
|
||||
if (found === false) {
|
||||
/*
|
||||
Before adding a new item to the array, we need to create a floatingObject of type Note. Once we set its basic parameters
|
||||
we can it to our array and to the floating layer.
|
||||
*/
|
||||
|
||||
let floatingObject = newFloatingObject()
|
||||
floatingObject.initialize('Note', '', floatingLayer)
|
||||
|
||||
floatingObject.payload = noteSet.payload
|
||||
floatingObject.payloadNoteIndex = i
|
||||
floatingObject.payloadImageId = noteSet.imageId
|
||||
|
||||
floatingObject.friction = 0.995
|
||||
|
||||
floatingObject.initializeMass(200)
|
||||
|
||||
// let bodyText = pNewNotes[i].body;
|
||||
let radius
|
||||
|
||||
/*
|
||||
if (bodyText.length < 100) {
|
||||
radius = 100;
|
||||
} else {
|
||||
radius = bodyText.length;
|
||||
}
|
||||
*/
|
||||
radius = 50
|
||||
|
||||
floatingObject.initializeRadius(radius)
|
||||
floatingObject.initializeImageSize(15)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 0.5)'
|
||||
floatingObject.labelStrokeStyle = 'rgba(60, 60, 60, 0.50)'
|
||||
|
||||
floatingLayer.addFloatingObject(floatingObject)
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> New Note added to Layer.') }
|
||||
|
||||
plotterNote.floatingHandle = floatingObject.handle
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> plotterNote.floatingHandle = ' + plotterNote.floatingHandle) }
|
||||
|
||||
newFloatingNotes.push(plotterNote)
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> Added to newFloatingNotes.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> newFloatingNotes.length = ' + newFloatingNotes.length) }
|
||||
} else {
|
||||
newFloatingNotes.push(floatingNote)
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> Old Note Kept.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> floatingNote.floatingHandle = ' + floatingNote.floatingHandle) }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> Added to newFloatingNotes.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> newFloatingNotes.length = ' + newFloatingNotes.length) }
|
||||
|
||||
let floatingObject = floatingLayer.getFloatingObject(floatingNote.floatingHandle)
|
||||
floatingObject.payloadNoteIndex = i
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> floatingObject index updated.') }
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> onInitialized -> floatingObject.payloadNoteIndex = ' + i) }
|
||||
}
|
||||
}
|
||||
|
||||
noteSet.floatingNotes = newFloatingNotes
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] createNoteSet -> onNotesChanged -> Add new Notes -> noteSet.floatingNotes.length = ' + noteSet.floatingNotes.length) }
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] createNoteSet -> onNotesChanged -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] createNoteSet -> err = ' + err.stack) }
|
||||
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE)
|
||||
}
|
||||
}
|
||||
|
||||
function destroyNoteSet (pHandle) {
|
||||
try {
|
||||
/*
|
||||
Usually when a bot is disabled by the end user, or the zoom level changes to one where the notes must not be seen, this method
|
||||
to destroy an entire NoteSet is executed. What we do in this situation is to localize the NoteSet to be destroyed and we need to
|
||||
kill, one by one the floating objects in it. Finally we remove this NoteSet item from the NoteSets array.
|
||||
*/
|
||||
|
||||
if (INFO_LOG === true) { logger.write('[INFO] destroyNoteSet -> Entering function.') }
|
||||
|
||||
for (let i = 0; i < noteSets.length; i++) {
|
||||
let noteSet = noteSets[i]
|
||||
|
||||
if (noteSet.handle === pHandle) {
|
||||
for (let j = 0; j < noteSet.floatingNotes.length; j++) {
|
||||
let floatingNote = noteSet.floatingNotes[j]
|
||||
|
||||
floatingLayer.removeFloatingObject(floatingNote.floatingHandle)
|
||||
}
|
||||
|
||||
noteSets.splice(i, 1) // Delete item from array.
|
||||
return
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] destroyNoteSet -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
|
||||
function newProfileBall () {
|
||||
const MODULE_NAME = 'Profile Ball'
|
||||
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
physics: physics,
|
||||
drawBackground: drawBackground,
|
||||
drawMiddleground: drawMiddleground,
|
||||
drawForeground: drawForeground,
|
||||
drawOnFocus: drawOnFocus,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize
|
||||
}
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME, 'Circle')
|
||||
thisObject.container.isClickeable = false
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.frame.radius = 0
|
||||
thisObject.container.frame.position.x = 0
|
||||
thisObject.container.frame.position.y = 0
|
||||
|
||||
let ballStringMenu = [
|
||||
{
|
||||
visible: false,
|
||||
iconPathOn: 'Images/menu.icon.on.1.gif',
|
||||
iconPathOff: 'Images/menu.icon.off.1.gif',
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
angle: 60
|
||||
}/*,
|
||||
{
|
||||
visible: false,
|
||||
iconPathOn: "Images/menu.icon.on.2.gif",
|
||||
iconPathOff: "Images/menu.icon.off.2.gif",
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
angle: 20 * 1
|
||||
},
|
||||
{
|
||||
visible: false,
|
||||
iconPathOn: "Images/menu.icon.on.3.gif",
|
||||
iconPathOff: "Images/menu.icon.off.3.gif",
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
angle: -20
|
||||
},
|
||||
{
|
||||
visible: false,
|
||||
iconPathOn: "Images/menu.icon.on.4.gif",
|
||||
iconPathOff: "Images/menu.icon.off.4.gif",
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
angle: -60
|
||||
} */
|
||||
]
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize () {
|
||||
for (let i = 0; i < ballStringMenu.length; i++) {
|
||||
let menuItem = ballStringMenu[i]
|
||||
menuItem.iconOn = new Image()
|
||||
menuItem.iconOn.onload = onImageLoad
|
||||
function onImageLoad () {
|
||||
menuItem.iconOff = new Image()
|
||||
menuItem.iconOff.onload = onImageLoad
|
||||
function onImageLoad () {
|
||||
menuItem.canDrawIcon = true
|
||||
}
|
||||
menuItem.iconOff.src = window.canvasApp.urlPrefix + menuItem.iconPathOff
|
||||
}
|
||||
menuItem.iconOn.src = window.canvasApp.urlPrefix + menuItem.iconPathOn
|
||||
menuItem.icon = menuItem.iconOn // The default value is ON.
|
||||
}
|
||||
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
let container
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
// The menuItems also have a target.
|
||||
|
||||
for (let i = 0; i < ballStringMenu.length; i++) {
|
||||
let menuItem = ballStringMenu[i]
|
||||
|
||||
if (Math.abs(menuItem.currentRadius - menuItem.targetRadius) >= 0.5) {
|
||||
if (menuItem.currentRadius < menuItem.targetRadius) {
|
||||
menuItem.currentRadius = menuItem.currentRadius + 0.5
|
||||
} else {
|
||||
menuItem.currentRadius = menuItem.currentRadius - 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseOver () {
|
||||
for (let i = 0; i < ballStringMenu.length; i++) {
|
||||
let menuItem = ballStringMenu[i]
|
||||
|
||||
menuItem.targetRadius = menuItem.rawRadius * 1.5
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseNotOver () {
|
||||
for (let i = 0; i < ballStringMenu.length; i++) {
|
||||
let menuItem = ballStringMenu[i]
|
||||
|
||||
menuItem.targetRadius = menuItem.rawRadius * 0 - i * 5
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
/* What we need to do here is to check which menu item was clicked, if any. */
|
||||
|
||||
pPoint = event.point
|
||||
pFloatingObject = event.parent
|
||||
|
||||
let menuItemIndex
|
||||
|
||||
for (let i = 0; i < ballStringMenu.length; i++) {
|
||||
let menuItem = ballStringMenu[i]
|
||||
|
||||
if (menuItem.canDrawIcon === true && menuItem.currentRadius > 1) {
|
||||
let position = {
|
||||
x: pFloatingObject.container.frame.position.x + pFloatingObject.currentImageSize / 2 * Math.cos(toRadians(menuItem.angle)),
|
||||
y: pFloatingObject.container.frame.position.y - pFloatingObject.currentImageSize / 2 * Math.sin(toRadians(menuItem.angle))
|
||||
}
|
||||
|
||||
browserCanvasContext.drawImage(menuItem.icon, position.x, position.y, menuItem.currentRadius * 2, menuItem.currentRadius * 2)
|
||||
|
||||
let distance = Math.sqrt(Math.pow(position.x - pPoint.x, 2) + Math.pow(position.y - pPoint.y, 2))
|
||||
|
||||
if (distance < menuItem.currentRadius) {
|
||||
menuItemIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (menuItemIndex !== undefined) {
|
||||
switch (menuItemIndex) {
|
||||
|
||||
case 0: {
|
||||
// This menu item is to turn ON / OFF the plotting of this bot.
|
||||
|
||||
if (pFloatingObject.payload.profile.plot === true) {
|
||||
pFloatingObject.payload.profile.plot = false
|
||||
|
||||
let menuItem = ballStringMenu[0]
|
||||
menuItem.icon = menuItem.iconOff
|
||||
} else {
|
||||
pFloatingObject.payload.profile.plot = true
|
||||
|
||||
let menuItem = ballStringMenu[0]
|
||||
menuItem.icon = menuItem.iconOn
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
case 1: {
|
||||
// This menu item is to turn ON the Debug Log pannel for the bot.
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawBackground (pFloatingObject) {
|
||||
let point = {
|
||||
x: pFloatingObject.payload.targetPosition.x,
|
||||
y: pFloatingObject.payload.targetPosition.y
|
||||
}
|
||||
|
||||
point = viewPort.fitIntoVisibleArea(point)
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 1) {
|
||||
/* Target Line */
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(pFloatingObject.container.frame.position.x, pFloatingObject.container.frame.position.y)
|
||||
browserCanvasContext.lineTo(point.x, point.y)
|
||||
browserCanvasContext.strokeStyle = 'rgba(204, 204, 204, 0.5)'
|
||||
browserCanvasContext.setLineDash([4, 2])
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.stroke()
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
}
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 0.5) {
|
||||
/* Target Spot */
|
||||
|
||||
var radius = 1
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(point.x, point.y, radius, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.fillStyle = 'rgba(30, 30, 30, 1)'
|
||||
browserCanvasContext.fill()
|
||||
}
|
||||
}
|
||||
|
||||
function drawOnFocus () {
|
||||
|
||||
}
|
||||
|
||||
function drawMiddleground () {
|
||||
|
||||
}
|
||||
|
||||
function drawForeground (pFloatingObject) {
|
||||
if (pFloatingObject.container.frame.radius > 5) {
|
||||
/* Contourn */
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(pFloatingObject.container.frame.position.x, pFloatingObject.container.frame.position.y, pFloatingObject.container.frame.radius, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(30, 30, 30, 0.75)'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 0.5) {
|
||||
/* Main FloatingObject */
|
||||
|
||||
var alphaA
|
||||
|
||||
if (pFloatingObject.container.frame.radius < 3) {
|
||||
alphaA = 1
|
||||
} else {
|
||||
alphaA = 0.75
|
||||
}
|
||||
|
||||
alphaA = 0.75
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(pFloatingObject.container.frame.position.x, pFloatingObject.container.frame.position.y, pFloatingObject.container.frame.radius, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fillStyle = pFloatingObject.fillStyle
|
||||
|
||||
browserCanvasContext.fill()
|
||||
}
|
||||
|
||||
/* Image */
|
||||
|
||||
if (pFloatingObject.payload.profile.imageId !== undefined) {
|
||||
let image = pFloatingObject.payload.profile.botAvatar
|
||||
|
||||
if (image !== null && image !== undefined) {
|
||||
browserCanvasContext.save()
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(pFloatingObject.container.frame.position.x, pFloatingObject.container.frame.position.y, pFloatingObject.currentImageSize / 2, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.clip()
|
||||
browserCanvasContext.drawImage(image, pFloatingObject.container.frame.position.x - pFloatingObject.currentImageSize / 2, pFloatingObject.container.frame.position.y - pFloatingObject.currentImageSize / 2, pFloatingObject.currentImageSize, pFloatingObject.currentImageSize)
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(pFloatingObject.container.frame.position.x - pFloatingObject.currentImageSize / 2, pFloatingObject.container.frame.position.y - pFloatingObject.currentImageSize / 2, pFloatingObject.currentImageSize / 2, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.clip()
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.restore()
|
||||
}
|
||||
}
|
||||
|
||||
/* StringBall Menu */
|
||||
|
||||
for (let i = 0; i < ballStringMenu.length; i++) {
|
||||
let menuItem = ballStringMenu[i]
|
||||
|
||||
if (menuItem.canDrawIcon === true && menuItem.currentRadius > 1) {
|
||||
let position = {
|
||||
x: pFloatingObject.container.frame.position.x + pFloatingObject.currentImageSize / 2 * Math.cos(toRadians(menuItem.angle)),
|
||||
y: pFloatingObject.container.frame.position.y - pFloatingObject.currentImageSize / 2 * Math.sin(toRadians(menuItem.angle))
|
||||
}
|
||||
|
||||
browserCanvasContext.drawImage(menuItem.icon, position.x - menuItem.currentRadius, position.y - menuItem.currentRadius, menuItem.currentRadius * 2, menuItem.currentRadius * 2)
|
||||
}
|
||||
}
|
||||
|
||||
/* Label Text */
|
||||
|
||||
if (pFloatingObject.container.frame.radius > 6) {
|
||||
browserCanvasContext.strokeStyle = pFloatingObject.labelStrokeStyle
|
||||
|
||||
let labelPoint
|
||||
let fontSize = pFloatingObject.currentFontSize
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
|
||||
let label
|
||||
|
||||
label = pFloatingObject.payload.profile.subTitle
|
||||
|
||||
if (label !== undefined) {
|
||||
labelPoint = {
|
||||
x: pFloatingObject.container.frame.position.x - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: pFloatingObject.container.frame.position.y - pFloatingObject.currentImageSize / 2 - fontSize * FONT_ASPECT_RATIO - 10
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = pFloatingObject.labelStrokeStyle
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
|
||||
label = pFloatingObject.payload.profile.title
|
||||
|
||||
if (label !== undefined) {
|
||||
labelPoint = {
|
||||
x: pFloatingObject.container.frame.position.x - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: pFloatingObject.container.frame.position.y + pFloatingObject.currentImageSize / 2 + fontSize * FONT_ASPECT_RATIO + 15
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = pFloatingObject.labelStrokeStyle
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
|
||||
function newProfileBalls () {
|
||||
const MODULE_NAME = 'Profile Balls'
|
||||
const INFO_LOG = false
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
/*
|
||||
|
||||
This object deals with Profile Balls, a type of Floating Object that shows profile info in a floating ball.
|
||||
|
||||
*/
|
||||
|
||||
let thisObject = {
|
||||
|
||||
createNewProfileBall: createNewProfileBall,
|
||||
destroyProfileBall: destroyProfileBall,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
|
||||
}
|
||||
|
||||
let floatingLayer
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize (pFloatingLayer) {
|
||||
floatingLayer = pFloatingLayer
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
floatingLayer.finalize()
|
||||
floatingLayer = undefined
|
||||
}
|
||||
|
||||
function createNewProfileBall (pPayload, callBackFunction) {
|
||||
let floatingObject = newFloatingObject()
|
||||
floatingObject.initialize('Profile Ball', '', floatingLayer)
|
||||
|
||||
floatingObject.payload = pPayload
|
||||
|
||||
floatingObject.friction = 0.995
|
||||
|
||||
floatingObject.initializeMass(100)
|
||||
floatingObject.initializeRadius(30)
|
||||
floatingObject.initializeImageSize(50)
|
||||
floatingObject.initializeFontSize(10)
|
||||
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 0.5)'
|
||||
floatingObject.labelStrokeStyle = 'rgba(60, 60, 60, 0.50)'
|
||||
|
||||
floatingLayer.addFloatingObject(floatingObject)
|
||||
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, floatingObject.handle)
|
||||
}
|
||||
|
||||
function destroyProfileBall (pFloatingObjectHandle) {
|
||||
floatingLayer.removeFloatingObject(pFloatingObjectHandle)
|
||||
}
|
||||
}
|
||||
|
||||
+155
-461
@@ -94,9 +94,16 @@ function newUiObject () {
|
||||
let currentValue = 0
|
||||
let rightDragging = false
|
||||
|
||||
let eventSubscriptionIdHeartbeat
|
||||
let eventSubscriptionIdOnStopped
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdHeartbeat, 'UiObject')
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdOnStopped, 'UiObject')
|
||||
|
||||
thisObject.container.eventHandler.stopListening(selfFocusEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(selfNotFocuskEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(selfDisplaceEventSubscriptionId)
|
||||
@@ -189,8 +196,33 @@ function newUiObject () {
|
||||
if (container !== undefined) { return container }
|
||||
}
|
||||
|
||||
container = thisObject.uiObjectTitle.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
let getitle = true
|
||||
|
||||
if (thisObject.codeEditor !== undefined) {
|
||||
if (thisObject.codeEditor.visible === true) {
|
||||
getitle = false
|
||||
}
|
||||
}
|
||||
if (thisObject.configEditor !== undefined) {
|
||||
if (thisObject.configEditor.visible === true) {
|
||||
getitle = false
|
||||
}
|
||||
}
|
||||
if (thisObject.conditionEditor !== undefined) {
|
||||
if (thisObject.conditionEditor.visible === true) {
|
||||
getitle = false
|
||||
}
|
||||
}
|
||||
if (thisObject.formulaEditor !== undefined) {
|
||||
if (thisObject.formulaEditor.visible === true) {
|
||||
getitle = false
|
||||
}
|
||||
}
|
||||
|
||||
if (getitle === true) {
|
||||
container = thisObject.uiObjectTitle.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
}
|
||||
|
||||
container = thisObject.menu.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
@@ -227,8 +259,10 @@ function newUiObject () {
|
||||
thisObject.payload.targetPosition.x = thisObject.payload.position.x,
|
||||
thisObject.payload.targetPosition.y = thisObject.payload.position.y
|
||||
} else {
|
||||
thisObject.payload.targetPosition.x = thisObject.payload.chainParent.payload.position.x
|
||||
thisObject.payload.targetPosition.y = thisObject.payload.chainParent.payload.position.y
|
||||
if (thisObject.payload.chainParent.payload.position !== undefined) {
|
||||
thisObject.payload.targetPosition.x = thisObject.payload.chainParent.payload.position.x
|
||||
thisObject.payload.targetPosition.y = thisObject.payload.chainParent.payload.position.y
|
||||
}
|
||||
}
|
||||
|
||||
if (thisObject.circularProgressBar !== undefined) {
|
||||
@@ -255,314 +289,18 @@ function newUiObject () {
|
||||
|
||||
let nearbyFloatingObjects = thisObject.payload.floatingObject.nearbyFloatingObjects
|
||||
let compatibleTypes
|
||||
let compatibleSubTypes
|
||||
switch (thisObject.payload.node.type) {
|
||||
case 'Sensor Bot':
|
||||
compatibleTypes = '->' + 'Team' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Indicator Bot':
|
||||
compatibleTypes = '->' + 'Team' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Trading Bot':
|
||||
compatibleTypes = '->' + 'Team' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Process Definition':
|
||||
compatibleTypes = '->' + 'Sensor Bot' + '->' + 'Indicator Bot' + '->' + 'Trading Bot' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Process Output':
|
||||
compatibleTypes = '->' + 'Process Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Process Dependencies':
|
||||
compatibleTypes = '->' + 'Process Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Status Report':
|
||||
compatibleTypes = '->' + 'Process Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Execution Started Event':
|
||||
compatibleTypes = '->' + 'Process Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Execution Finished Event':
|
||||
compatibleTypes = '->' + 'Process Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Calculations Procedure':
|
||||
compatibleTypes = '->' + 'Product Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Data Building Procedure':
|
||||
compatibleTypes = '->' + 'Product Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Procedure Initialization':
|
||||
compatibleTypes = '->' + 'Calculations Procedure' + '->' + 'Data Building Procedure' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Procedure Loop':
|
||||
compatibleTypes = '->' + 'Calculations Procedure' + '->' + 'Data Building Procedure' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Output Dataset':
|
||||
compatibleTypes = '->' + 'Process Output' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Status Dependency':
|
||||
compatibleTypes = '->' + 'Process Dependencies' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Data Dependency':
|
||||
compatibleTypes = '->' + 'Process Dependencies' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Product Definition':
|
||||
compatibleTypes = '->' + 'Sensor Bot' + '->' + 'Indicator Bot' + '->' + 'Trading Bot' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Record Definition':
|
||||
compatibleTypes = '->' + 'Product Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Record Property':
|
||||
compatibleTypes = '->' + 'Record Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Dataset Definition':
|
||||
compatibleTypes = '->' + 'Product Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Plotter':
|
||||
compatibleTypes = '->' + 'Team' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Plotter Module':
|
||||
compatibleTypes = '->' + 'Plotter' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Trading System':
|
||||
compatibleTypes = '->' + 'Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Personal Data':
|
||||
compatibleTypes = '->' + 'Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Network Node':
|
||||
compatibleTypes = '->' + 'Network' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Exchange Account':
|
||||
compatibleTypes = '->' + 'Personal Data' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Exchange Account Asset':
|
||||
compatibleTypes = '->' + 'Exchange Account' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Exchange Account Key':
|
||||
compatibleTypes = '->' + 'Exchange Account' + '->' + 'Parameters' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Parameters':
|
||||
compatibleTypes = '->' + 'Trading System' + '->' + 'Backtesting Session' + '->' + 'Live Trading Session' + '->' + 'Paper Trading Session' + '->' + 'Fordward Testing Session' + '->'
|
||||
compatibleSubTypes = '->' + 'Trading Process Instance' + '->'
|
||||
break
|
||||
case 'Backtesting Session':
|
||||
compatibleTypes = '->' + 'Process Instance' + '->'
|
||||
compatibleSubTypes = '->' + 'Trading Process Instance' + '->'
|
||||
break
|
||||
case 'Live Trading Session':
|
||||
compatibleTypes = '->' + 'Process Instance' + '->'
|
||||
compatibleSubTypes = '->' + 'Trading Process Instance' + '->'
|
||||
break
|
||||
case 'Paper Trading Session':
|
||||
compatibleTypes = '->' + 'Process Instance' + '->'
|
||||
compatibleSubTypes = '->' + 'Trading Process Instance' + '->'
|
||||
break
|
||||
case 'Fordward Testing Session':
|
||||
compatibleTypes = '->' + 'Process Instance' + '->'
|
||||
compatibleSubTypes = '->' + 'Trading Process Instance' + '->'
|
||||
break
|
||||
case 'Base Asset':
|
||||
compatibleTypes = '->' + 'Parameters' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Time Range':
|
||||
compatibleTypes = '->' + 'Parameters' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Time Period':
|
||||
compatibleTypes = '->' + 'Parameters' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Slippage':
|
||||
compatibleTypes = '->' + 'Parameters' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Fee Structure':
|
||||
compatibleTypes = '->' + 'Parameters' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Layer Manager':
|
||||
compatibleTypes = '->' + 'Backtesting Session' + '->' + 'Live Trading Session' + '->' + 'Paper Trading Session' + '->' + 'Fordward Testing Session' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Layer':
|
||||
compatibleTypes = '->' + 'Layer Manager' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Social Bots':
|
||||
compatibleTypes = '->' + 'Backtesting Session' + '->' + 'Live Trading Session' + '->' + 'Paper Trading Session' + '->' + 'Fordward Testing Session' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Telegram Bot':
|
||||
compatibleTypes = '->' + 'Social Bots' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Announcement':
|
||||
compatibleTypes = '->' + 'Telegram Bot' + '->' + 'Trigger On Event' + '->' + 'Trigger Off Event' + '->' + 'Take Position Event' + '->' + 'Next Phase Event' + '->' + '->' + 'Phase' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Task Manager':
|
||||
compatibleTypes = '->' + 'Network Node' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Task':
|
||||
compatibleTypes = '->' + 'Task Manager' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Sensor Bot Instance':
|
||||
compatibleTypes = '->' + 'Task' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Indicator Bot Instance':
|
||||
compatibleTypes = '->' + 'Task' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Trading Bot Instance':
|
||||
compatibleTypes = '->' + 'Task' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Process Instance':
|
||||
switch (thisObject.payload.node.subType) {
|
||||
case 'Sensor Process Instance': {
|
||||
compatibleTypes = '->' + 'Sensor Bot Instance' + '->'
|
||||
break
|
||||
}
|
||||
case 'Indicator Process Instance': {
|
||||
compatibleTypes = '->' + 'Indicator Bot Instance' + '->'
|
||||
break
|
||||
}
|
||||
case 'Trading Process Instance': {
|
||||
compatibleTypes = '->' + 'Trading Bot Instance' + '->'
|
||||
break
|
||||
}
|
||||
}
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Strategy':
|
||||
compatibleTypes = '->' + 'Trading System' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Trigger Stage':
|
||||
compatibleTypes = '->' + 'Strategy' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Open Stage':
|
||||
compatibleTypes = '->' + 'Strategy' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Manage Stage':
|
||||
compatibleTypes = '->' + 'Strategy' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Close Stage':
|
||||
compatibleTypes = '->' + 'Strategy' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Position Size':
|
||||
compatibleTypes = '->' + 'Initial Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Position Rate':
|
||||
compatibleTypes = '->' + 'Initial Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Take Position Event':
|
||||
compatibleTypes = '->' + 'Trigger Stage' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Trigger Off Event':
|
||||
compatibleTypes = '->' + 'Trigger Stage' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Trigger On Event':
|
||||
compatibleTypes = '->' + 'Trigger Stage' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Initial Definition':
|
||||
compatibleTypes = '->' + 'Open Stage' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Open Execution':
|
||||
compatibleTypes = '->' + 'Open Stage' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Close Execution':
|
||||
compatibleTypes = '->' + 'Close Stage' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Stop':
|
||||
compatibleTypes = '->' + 'Manage Stage' + '->' + 'Initial Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Take Profit':
|
||||
compatibleTypes = '->' + 'Manage Stage' + '->' + 'Initial Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Phase':
|
||||
compatibleTypes = '->' + 'Stop' + '->' + 'Take Profit' + '->' + 'Phase' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Formula':
|
||||
compatibleTypes = '->' + 'Position Size' + '->' + 'Position Rate' + '->' + 'Phase' + '->' + 'Announcement' + '->' + 'Record Property' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Next Phase Event':
|
||||
compatibleTypes = '->' + 'Phase' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Situation':
|
||||
compatibleTypes = '->' + 'Take Position Event' + '->' + 'Trigger On Event' + '->' + 'Trigger Off Event' + '->' + 'Next Phase Event' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Condition':
|
||||
compatibleTypes = '->' + 'Situation' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Javascript Code':
|
||||
compatibleTypes = '->' + 'Condition' + '->' + 'Procedure Initialization' + '->' + 'Procedure Loop' + '->' + 'Plotter Module' + '->' + 'Plotter Panel' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
default:
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.chainAttachesTo !== undefined) {
|
||||
compatibleTypes = nodeDefinition.chainAttachesTo.compatibleTypes
|
||||
compatibleSubTypes = nodeDefinition.chainAttachesTo.compatibleSubTypes
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.chainAttachesTo !== undefined) {
|
||||
compatibleTypes = nodeDefinition.chainAttachesTo.compatibleTypes
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
let foundCompatible = false
|
||||
chainAttachToNode = undefined
|
||||
isChainAttaching = false
|
||||
@@ -574,7 +312,7 @@ function newUiObject () {
|
||||
let nearbyNode = floatingObject.payload.node
|
||||
if (compatibleTypes.indexOf('->' + nearbyNode.type + '->') >= 0) {
|
||||
/* Discard App Schema defined objects with busy coonection ports */
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
let mustContinue = false
|
||||
let parentNodeDefinition = APP_SCHEMA_MAP.get(nearbyNode.type)
|
||||
@@ -601,55 +339,7 @@ function newUiObject () {
|
||||
}
|
||||
if (mustContinue === true) { continue }
|
||||
}
|
||||
/* Discard legacy objects with busy coonection ports */
|
||||
if (thisObject.payload.node.type === 'Status Report' && nearbyNode.statusReport !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Execution Started Event' && nearbyNode.executionStartedEvent !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Execution Finished Event' && nearbyNode.executionFinishedEvent !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Calculations Procedure' && nearbyNode.calculations !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Data Building Procedure' && nearbyNode.dataBuilding !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Procedure Initialization' && nearbyNode.initialization !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Procedure Loop' && nearbyNode.loop !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Record Definition' && nearbyNode.record !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Task' && nearbyNode.task !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Sensor Bot Instance' && nearbyNode.bot !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Indicator Bot Instance' && nearbyNode.bot !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Trading Bot Instance' && nearbyNode.bot !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Process Instance' && nearbyNode.process !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Trading System' && nearbyNode.tradingSystem !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Personal Data' && nearbyNode.personalData !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Parameters' && nearbyNode.parameters !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Backtesting Session' && nearbyNode.session !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Live Trading Session' && nearbyNode.session !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Fordward Testing Session' && nearbyNode.session !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Paper Trading Session' && nearbyNode.session !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Base Asset' && nearbyNode.baseAsset !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Time Range' && nearbyNode.timeRange !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Time Period' && nearbyNode.timePeriod !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Slippage' && nearbyNode.slippage !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Fee Structure' && nearbyNode.feeStructure !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Trigger Stage' && nearbyNode.triggerStage !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Open Stage' && nearbyNode.openStage !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Manage Stage' && nearbyNode.manageStage !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Close Stage' && nearbyNode.closeStage !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Position Size' && nearbyNode.positionSize !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Position Rate' && nearbyNode.positionRate !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Take Position Event' && nearbyNode.takePosition !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Trigger Off Event' && nearbyNode.triggerOff !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Trigger On Event' && nearbyNode.triggerOn !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Initial Definition' && nearbyNode.initialDefinition !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Open Execution' && nearbyNode.openExecution !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Close Execution' && nearbyNode.closeExecution !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Stop' && nearbyNode.stopLoss !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Take Profit' && nearbyNode.takeProfit !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Formula' && nearbyNode.formula !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Next Phase Event' && nearbyNode.nextPhaseEvent !== undefined) { continue }
|
||||
if (thisObject.payload.node.type === 'Javascript Code' && nearbyNode.javascriptCode !== undefined) { continue }
|
||||
/* Here we check if the subtypes are compatible. */
|
||||
if (nearbyNode.subType !== undefined && compatibleSubTypes !== undefined) {
|
||||
if (compatibleSubTypes.indexOf('->' + nearbyNode.subType + '->') < 0) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
/* Discard Phases without partent */
|
||||
if (thisObject.payload.node.type === 'Phase' && nearbyNode.type === 'Phase' && nearbyNode.payload.parentNode === undefined) { continue }
|
||||
/* Control maxPhases */
|
||||
@@ -752,61 +442,18 @@ function newUiObject () {
|
||||
|
||||
let nearbyFloatingObjects = thisObject.payload.floatingObject.nearbyFloatingObjects
|
||||
let compatibleTypes
|
||||
let compatibleSubTypes
|
||||
switch (thisObject.payload.node.type) {
|
||||
case 'Backtesting Session':
|
||||
compatibleTypes = '->' + 'Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Live Trading Session':
|
||||
compatibleTypes = '->' + 'Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Paper Trading Session':
|
||||
compatibleTypes = '->' + 'Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Fordward Testing Session':
|
||||
compatibleTypes = '->' + 'Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Output Dataset':
|
||||
compatibleTypes = '->' + 'Dataset Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Data Dependency':
|
||||
compatibleTypes = '->' + 'Dataset Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Status Dependency':
|
||||
compatibleTypes = '->' + 'Status Report' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Execution Started Event':
|
||||
compatibleTypes = '->' + 'Execution Finished Event' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Process Instance':
|
||||
compatibleTypes = '->' + 'Process Definition' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
case 'Product Definition':
|
||||
compatibleTypes = '->' + 'Plotter Module' + '->'
|
||||
compatibleSubTypes = undefined
|
||||
break
|
||||
default:
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.referenceAttachesTo !== undefined) {
|
||||
compatibleTypes = nodeDefinition.referenceAttachesTo.compatibleTypes
|
||||
compatibleSubTypes = nodeDefinition.referenceAttachesTo.compatibleSubTypes
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.referenceAttachesTo !== undefined) {
|
||||
compatibleTypes = nodeDefinition.referenceAttachesTo.compatibleTypes
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
let foundCompatible = false
|
||||
referenceAttachToNode = undefined
|
||||
isReferenceAttaching = false
|
||||
@@ -817,13 +464,6 @@ function newUiObject () {
|
||||
let floatingObject = nearby[1]
|
||||
let nearbyNode = floatingObject.payload.node
|
||||
if (compatibleTypes.indexOf('->' + nearbyNode.type + '->') >= 0) {
|
||||
/* Here we check if the subtypes are compatible. */
|
||||
if (nearbyNode.subType !== undefined && compatibleSubTypes !== undefined) {
|
||||
if (compatibleSubTypes.indexOf('->' + nearbyNode.subType + '->') < 0) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (foundCompatible === false) {
|
||||
if (distance < thisObject.container.frame.radius * 1.5 + floatingObject.container.frame.radius * 1.5) {
|
||||
nearbyNode.payload.uiObject.getReadyToReferenceAttach()
|
||||
@@ -956,11 +596,19 @@ function newUiObject () {
|
||||
thisObject.circularProgressBar.fitFunction = thisObject.fitFunction
|
||||
thisObject.circularProgressBar.container = thisObject.container
|
||||
|
||||
/* We will wait to the event that the execution was terminated in order to call back the menu item */
|
||||
/* We will wait to hear the first onHeartBeat in order to confirm the execution was really started */
|
||||
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
|
||||
systemEventHandler.listenToEvent(key, 'Running', undefined, key, undefined, onRunning)
|
||||
systemEventHandler.listenToEvent(key, 'Heartbeat', undefined, 'UiObject', onResponse, onHeartBeat)
|
||||
|
||||
function onResponse (message) {
|
||||
eventSubscriptionIdHeartbeat = message.eventSubscriptionId
|
||||
}
|
||||
|
||||
function onHeartBeat () {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
|
||||
systemEventHandler.stopListening(key, eventSubscriptionIdHeartbeat, 'UiObject')
|
||||
|
||||
function onRunning () {
|
||||
if (callBackFunction !== undefined) {
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
}
|
||||
@@ -988,9 +636,14 @@ function newUiObject () {
|
||||
function stop (callBackFunction, event) {
|
||||
/* We will wait to the event that the execution was terminated in order to call back the menu item */
|
||||
let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id
|
||||
systemEventHandler.listenToEvent(key, 'Stopped', undefined, key, undefined, onStopped)
|
||||
systemEventHandler.listenToEvent(key, 'Stopped', undefined, 'UiObject', onResponse, onStopped)
|
||||
|
||||
function onResponse (message) {
|
||||
eventSubscriptionIdOnStopped = message.eventSubscriptionId
|
||||
}
|
||||
|
||||
function onStopped () {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
if (callBackFunction !== undefined) {
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, event)
|
||||
}
|
||||
@@ -1005,6 +658,42 @@ function newUiObject () {
|
||||
|
||||
function iconPhysics () {
|
||||
icon = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition.alternativeIcons !== undefined) {
|
||||
let nodeToUse = thisObject.payload.node
|
||||
if (nodeDefinition.alternativeIcons === 'Use Reference Parent') {
|
||||
if (thisObject.payload.node.payload.referenceParent !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent
|
||||
}
|
||||
}
|
||||
if (nodeDefinition.alternativeIcons === 'Use Reference Grandparent') {
|
||||
if (thisObject.payload.node.payload.referenceParent !== undefined) {
|
||||
if (thisObject.payload.node.payload.referenceParent.payload.referenceParent !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.referenceParent
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeDefinition = APP_SCHEMA_MAP.get(nodeToUse.type)
|
||||
let code = nodeToUse.code
|
||||
try {
|
||||
code = JSON.parse(code)
|
||||
let alternativeIcon
|
||||
let iconName
|
||||
for (let i = 0; i < nodeDefinition.alternativeIcons.length; i++) {
|
||||
alternativeIcon = nodeDefinition.alternativeIcons[i]
|
||||
if (alternativeIcon.codeName === code.codeName) {
|
||||
iconName = alternativeIcon.iconName
|
||||
}
|
||||
}
|
||||
let newIcon = canvas.designerSpace.iconCollection.get(iconName)
|
||||
if (newIcon !== undefined) {
|
||||
icon = newIcon
|
||||
}
|
||||
} catch (err) {
|
||||
// Nothing to do if JSON is baddly formated.
|
||||
}
|
||||
}
|
||||
|
||||
executingIcon = canvas.designerSpace.iconCollection.get('attractive')
|
||||
}
|
||||
|
||||
@@ -1130,25 +819,30 @@ function newUiObject () {
|
||||
}
|
||||
|
||||
let drawMenu = true
|
||||
let drawTitle = true
|
||||
|
||||
if (thisObject.codeEditor !== undefined) {
|
||||
if (thisObject.codeEditor.visible === true) {
|
||||
drawMenu = false
|
||||
drawTitle = false
|
||||
}
|
||||
}
|
||||
if (thisObject.configEditor !== undefined) {
|
||||
if (thisObject.configEditor.visible === true) {
|
||||
drawMenu = false
|
||||
drawTitle = false
|
||||
}
|
||||
}
|
||||
if (thisObject.conditionEditor !== undefined) {
|
||||
if (thisObject.conditionEditor.visible === true) {
|
||||
drawMenu = false
|
||||
drawTitle = false
|
||||
}
|
||||
}
|
||||
if (thisObject.formulaEditor !== undefined) {
|
||||
if (thisObject.formulaEditor.visible === true) {
|
||||
drawMenu = false
|
||||
drawTitle = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1163,7 +857,10 @@ function newUiObject () {
|
||||
drawErrorMessage()
|
||||
drawValue()
|
||||
drawText()
|
||||
thisObject.uiObjectTitle.draw()
|
||||
|
||||
if (drawTitle === true) {
|
||||
thisObject.uiObjectTitle.draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1171,8 +868,8 @@ function newUiObject () {
|
||||
if (thisObject.payload.chainParent === undefined) { return }
|
||||
|
||||
let targetPoint = {
|
||||
x: thisObject.payload.targetPosition.x,
|
||||
y: thisObject.payload.targetPosition.y
|
||||
x: thisObject.payload.chainParent.payload.floatingObject.container.frame.position.x,
|
||||
y: thisObject.payload.chainParent.payload.floatingObject.container.frame.position.y
|
||||
}
|
||||
|
||||
let position = {
|
||||
@@ -1184,10 +881,8 @@ function newUiObject () {
|
||||
position = thisObject.container.frame.frameThisPoint(position)
|
||||
|
||||
if (thisObject.container.frame.radius > 1) {
|
||||
/* Target Line */
|
||||
|
||||
let LINE_STYLE = UI_COLOR.TITANIUM_YELLOW
|
||||
if (thisObject.payload.floatingObject.isTensed === true) {
|
||||
if (thisObject.payload.floatingObject.angleToParent !== ANGLE_TO_PARENT.NOT_FIXED) {
|
||||
LINE_STYLE = UI_COLOR.GOLDEN_ORANGE
|
||||
}
|
||||
if (thisObject.payload.floatingObject.isFrozen === true) {
|
||||
@@ -1214,8 +909,6 @@ function newUiObject () {
|
||||
}
|
||||
|
||||
if (thisObject.container.frame.radius > 0.5) {
|
||||
/* Target Spot */
|
||||
|
||||
let radius = 1
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
@@ -1248,8 +941,6 @@ function newUiObject () {
|
||||
let LINE_STYLE = UI_COLOR.GREY
|
||||
|
||||
if (thisObject.container.frame.radius > 1) {
|
||||
/* Target Line */
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(position.x, position.y)
|
||||
browserCanvasContext.lineTo(targetPoint.x, targetPoint.y)
|
||||
@@ -1270,8 +961,6 @@ function newUiObject () {
|
||||
}
|
||||
|
||||
if (thisObject.container.frame.radius > 0.5) {
|
||||
/* Target Spot */
|
||||
|
||||
let radius = 1
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
@@ -1377,11 +1066,13 @@ function newUiObject () {
|
||||
let label
|
||||
|
||||
if (radius > 6) {
|
||||
const MAX_LABEL_LENGTH = 30
|
||||
const MAX_LABEL_LENGTH = 65
|
||||
|
||||
label = currentValue
|
||||
if (!isNaN(label)) {
|
||||
label = currentValue.toFixed(2)
|
||||
if (currentValue.toFixed !== undefined) {
|
||||
label = currentValue.toFixed(2)
|
||||
}
|
||||
}
|
||||
|
||||
if (label !== undefined) {
|
||||
@@ -1500,25 +1191,28 @@ function newUiObject () {
|
||||
|
||||
browserCanvasContext.fill()
|
||||
|
||||
if (thisObject.payload.node.type === 'Definition' || thisObject.payload.node.type === 'Network' || thisObject.payload.node.type === 'Team') {
|
||||
VISIBLE_RADIUS = thisObject.container.frame.radius * 2
|
||||
let OPACITY = 1
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.isHierarchyHead === true) {
|
||||
VISIBLE_RADIUS = thisObject.container.frame.radius * 2
|
||||
let OPACITY = 1
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = 10
|
||||
browserCanvasContext.setLineDash([4, 16])
|
||||
browserCanvasContext.stroke()
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = 10
|
||||
browserCanvasContext.setLineDash([4, 16])
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.setLineDash([20, 20])
|
||||
browserCanvasContext.stroke()
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.setLineDash([20, 20])
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
if (thisObject.isOnFocus === true) {
|
||||
@@ -1619,7 +1313,7 @@ function newUiObject () {
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GOLDEN_ORANGE + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = 10
|
||||
browserCanvasContext.setLineDash([10, 90])
|
||||
browserCanvasContext.stroke()
|
||||
@@ -1627,7 +1321,7 @@ function newUiObject () {
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GOLDEN_ORANGE + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = 5
|
||||
browserCanvasContext.setLineDash([5, 45])
|
||||
browserCanvasContext.stroke()
|
||||
@@ -1635,7 +1329,7 @@ function newUiObject () {
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(visiblePosition.x, visiblePosition.y, VISIBLE_RADIUS, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.LIGHT_GREY + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.GOLDEN_ORANGE + ', ' + OPACITY + ')'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.setLineDash([2, 8])
|
||||
browserCanvasContext.stroke()
|
||||
@@ -1668,7 +1362,7 @@ function newUiObject () {
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
let additionalImageSize = 0
|
||||
if (thisObject.isExecuting === true) { additionalImageSize = 20 }
|
||||
if (thisObject.isExecuting === true || isReadyToReferenceAttach === true || isReadyToChainAttach === true) { additionalImageSize = 20 }
|
||||
let totalImageSize = additionalImageSize + thisObject.payload.floatingObject.currentImageSize
|
||||
|
||||
browserCanvasContext.drawImage(
|
||||
|
||||
@@ -31,15 +31,21 @@ function newUiObjectConstructor () {
|
||||
floatingObject.initialize('UI Object', payload)
|
||||
payload.floatingObject = floatingObject
|
||||
|
||||
if (payload.node.savedPayload !== undefined) {
|
||||
/*
|
||||
When this object is created based on a backup, share or clone, we will have a savedPayload that we will use to set the initial properties.
|
||||
If it is a new object being created out of the user interface, we jusst continue with the construction process.
|
||||
*/
|
||||
if (userAddingNew === false && payload.node.type !== 'Workspace') {
|
||||
let position = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
position = {
|
||||
x: payload.node.savedPayload.position.x,
|
||||
y: payload.node.savedPayload.position.y
|
||||
}
|
||||
|
||||
if (position.x === null) { position.x = spawnPosition.x }
|
||||
if (position.y === null) { position.y = spawnPosition.y }
|
||||
|
||||
floatingObject.setPosition(position)
|
||||
payload.node.savedPayload.position = undefined
|
||||
if (payload.node.savedPayload.floatingObject.isPinned === true) {
|
||||
@@ -51,16 +57,18 @@ function newUiObjectConstructor () {
|
||||
if (payload.node.savedPayload.floatingObject.isCollapsed === true) {
|
||||
floatingObject.collapseToggle()
|
||||
}
|
||||
if (payload.node.savedPayload.floatingObject.isTensed === true) {
|
||||
floatingObject.tensionToggle()
|
||||
if (payload.node.savedPayload.floatingObject.angleToParent !== undefined) {
|
||||
floatingObject.angleToParent = payload.node.savedPayload.floatingObject.angleToParent
|
||||
}
|
||||
if (payload.node.savedPayload.floatingObject.distanceToParent !== undefined) {
|
||||
floatingObject.distanceToParent = payload.node.savedPayload.floatingObject.distanceToParent
|
||||
}
|
||||
}
|
||||
|
||||
/* For brand new objects being created directly by the user, we will make them inherit some properties from their parents. */
|
||||
if (userAddingNew === true) {
|
||||
/* For brand new objects being created directly by the user, we will make them inherit some properties from their parents. */
|
||||
if (payload.parentNode.payload.floatingObject.isTensed === true) {
|
||||
floatingObject.tensionToggle()
|
||||
}
|
||||
floatingObject.angleToParent = payload.parentNode.payload.floatingObject.angleToParent
|
||||
floatingObject.distanceToParent = payload.parentNode.payload.floatingObject.distanceToParent
|
||||
}
|
||||
|
||||
let uiObject = newUiObject()
|
||||
@@ -76,8 +84,8 @@ function newUiObjectConstructor () {
|
||||
for (let j = 0; j < menuItems.length; j++) {
|
||||
let item = menuItems[j]
|
||||
item.angle = undefined
|
||||
if (item.action.indexOf('Add ') >= 0) {
|
||||
// item.action = 'Add UI Object'
|
||||
if (item.action.indexOf('Add ') >= 0 && item.action.indexOf('Missing') >= 0) {
|
||||
item.action = 'Add Missing Children'
|
||||
}
|
||||
if (item.action.indexOf('Delete ') >= 0) {
|
||||
// item.action = 'Delete UI Object'
|
||||
@@ -128,24 +136,40 @@ function newUiObjectConstructor () {
|
||||
iconPathOff: 'menu-fix-unpinned',
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
}
|
||||
)
|
||||
menuItemsInitialValues.push(
|
||||
{
|
||||
action: 'Tense / Untense',
|
||||
actionFunction: floatingObject.tensionToggle,
|
||||
actionStatus: floatingObject.getTensionStatus,
|
||||
action: 'Change Tension Level',
|
||||
actionFunction: floatingObject.angleToParentToggle,
|
||||
actionStatus: floatingObject.getAngleToParent,
|
||||
currentStatus: true,
|
||||
label: undefined,
|
||||
visible: true,
|
||||
iconPathOn: 'menu-tensor-fixed-angles',
|
||||
iconPathOff: 'menu-tensor-free-angles',
|
||||
icons: ['angle-to-parent-000', 'angle-to-parent-360', 'angle-to-parent-180', 'angle-to-parent-090', 'angle-to-parent-045'],
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
}
|
||||
)
|
||||
menuItemsInitialValues.push(
|
||||
{
|
||||
action: 'change Distance to Paarent',
|
||||
actionFunction: floatingObject.distanceToParentToggle,
|
||||
actionStatus: floatingObject.getDistanceToParent,
|
||||
currentStatus: true,
|
||||
label: undefined,
|
||||
visible: true,
|
||||
icons: ['distance-to-parent-000', 'distance-to-parent-025', 'distance-to-parent-050', 'distance-to-parent-100', 'distance-to-parent-150', 'distance-to-parent-200'],
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
}
|
||||
)
|
||||
menuItemsInitialValues.push(
|
||||
{
|
||||
action: 'Freeze / Unfreeze',
|
||||
@@ -158,7 +182,8 @@ function newUiObjectConstructor () {
|
||||
iconPathOff: 'menu-mobility-freeze',
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
}
|
||||
)
|
||||
menuItemsInitialValues.push(
|
||||
@@ -173,7 +198,8 @@ function newUiObjectConstructor () {
|
||||
iconPathOff: 'menu-tree-minus',
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0
|
||||
currentRadius: 0,
|
||||
ring: 1
|
||||
}
|
||||
)
|
||||
menuItemsInitialValues.push(
|
||||
@@ -186,7 +212,8 @@ function newUiObjectConstructor () {
|
||||
iconPathOff: 'menu-backup',
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0
|
||||
currentRadius: 0,
|
||||
ring: 2
|
||||
}
|
||||
)
|
||||
menuItemsInitialValues.push(
|
||||
@@ -199,7 +226,8 @@ function newUiObjectConstructor () {
|
||||
iconPathOff: 'clone',
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0
|
||||
currentRadius: 0,
|
||||
ring: 2
|
||||
}
|
||||
)
|
||||
if (isPersonalData !== true) {
|
||||
@@ -213,9 +241,10 @@ function newUiObjectConstructor () {
|
||||
iconPathOff: 'menu-share',
|
||||
rawRadius: 8,
|
||||
targetRadius: 0,
|
||||
currentRadius: 0
|
||||
currentRadius: 0,
|
||||
ring: 2
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +331,7 @@ function newUiObjectConstructor () {
|
||||
switch (payload.node.type) {
|
||||
case 'Workspace': {
|
||||
level_0()
|
||||
floatingObject.angleToParent = ANGLE_TO_PARENT.RANGE_360
|
||||
break
|
||||
}
|
||||
|
||||
@@ -361,7 +391,7 @@ function newUiObjectConstructor () {
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
|
||||
if (payload.node.savedPayload === undefined) {
|
||||
// floatingObject.tensionToggle()
|
||||
// floatingObject.angleToParentToggle()
|
||||
}
|
||||
}
|
||||
function level_2 () {
|
||||
@@ -376,7 +406,7 @@ function newUiObjectConstructor () {
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.GREEN + ', 1)'
|
||||
|
||||
if (payload.node.savedPayload === undefined) {
|
||||
// floatingObject.tensionToggle()
|
||||
// floatingObject.angleToParentToggle()
|
||||
}
|
||||
}
|
||||
function level_3 () {
|
||||
@@ -391,7 +421,7 @@ function newUiObjectConstructor () {
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', 1)'
|
||||
|
||||
if (payload.node.savedPayload === undefined) {
|
||||
// floatingObject.tensionToggle()
|
||||
// floatingObject.angleToParentToggle()
|
||||
}
|
||||
}
|
||||
function level_4 () {
|
||||
@@ -406,7 +436,7 @@ function newUiObjectConstructor () {
|
||||
floatingObject.fillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 1)'
|
||||
|
||||
if (payload.node.savedPayload === undefined) {
|
||||
// floatingObject.tensionToggle()
|
||||
// floatingObject.angleToParentToggle()
|
||||
}
|
||||
}
|
||||
function level_5 () {
|
||||
|
||||
+71
-103
@@ -48,106 +48,10 @@ function newUiObjectTitle () {
|
||||
thisObject.payload = payload
|
||||
|
||||
thisObject.allwaysVisible = false // Default value
|
||||
switch (payload.node.type) {
|
||||
case 'Definition': {
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.isTitleAllwaysVisible === true) {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Team': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Sensor Bot': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Indicator Bot': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Trading Bot': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Process Definition': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Product Definition': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Dataset Definition': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Record Property': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Plotter': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Plotter Module': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Network': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Announcement': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Layer': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Sensor Bot Instance': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Indicator Bot Instance': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Backtesting Session': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Live Trading Session': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Fordward Testing Session': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Paper Trading Session': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Workspace': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Trading System': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
case 'Strategy': {
|
||||
thisObject.allwaysVisible = true
|
||||
break
|
||||
}
|
||||
default: {
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition !== undefined) {
|
||||
if (nodeDefinition.isTitleAllwaysVisible === true) {
|
||||
thisObject.allwaysVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,12 +82,73 @@ function newUiObjectTitle () {
|
||||
|
||||
function physics () {
|
||||
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)
|
||||
if (nodeDefinition.title !== undefined) {
|
||||
thisObject.payload.title = ''
|
||||
thisObject.payload.node.name = ''
|
||||
let separator = ''
|
||||
for (let i = 0; i < nodeDefinition.title.length; i++) {
|
||||
let titleReference = nodeDefinition.title[i]
|
||||
switch (titleReference) {
|
||||
case 'Use Reference Parent': {
|
||||
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
||||
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'Use Reference Grandparent': {
|
||||
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.referenceParent
|
||||
if (nodeToUse !== undefined) {
|
||||
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
||||
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'Use Reference Parent Parent': {
|
||||
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
||||
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'Use Reference Parent Parent Parent': {
|
||||
let nodeToUse = thisObject.payload.node.payload.referenceParent
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
nodeToUse = thisObject.payload.node.payload.referenceParent.payload.parentNode.payload.parentNode
|
||||
if (nodeToUse !== undefined && nodeToUse.payload !== undefined) {
|
||||
thisObject.payload.title = thisObject.payload.title + separator + nodeToUse.payload.title
|
||||
thisObject.payload.node.name = thisObject.payload.node.name + separator + nodeToUse.payload.node.name
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
separator = ' '
|
||||
}
|
||||
}
|
||||
|
||||
let title = trimTitle(thisObject.payload.title)
|
||||
|
||||
/* Here we set the dimensions and position of this object */
|
||||
const FRAME_HEIGHT = 25
|
||||
const FRAME_WIDTH = title.length / 2 * thisObject.payload.floatingObject.currentFontSize * FONT_ASPECT_RATIO * 1.2 * 2
|
||||
const Y_OFFSET = -20
|
||||
const FRAME_WIDTH = (title.length + 2) / 2 * thisObject.payload.floatingObject.currentFontSize * FONT_ASPECT_RATIO * 1.2 * 2
|
||||
thisObject.container.frame.position.x = 0 - FRAME_WIDTH / 2
|
||||
thisObject.container.frame.position.y = 0 - thisObject.container.frame.radius * 1 / 2 - thisObject.payload.floatingObject.currentFontSize * FONT_ASPECT_RATIO - 20 - FRAME_HEIGHT
|
||||
thisObject.container.frame.position.y = 0 - thisObject.container.frame.radius * 1 / 2 - thisObject.payload.floatingObject.currentFontSize * FONT_ASPECT_RATIO + Y_OFFSET - FRAME_HEIGHT
|
||||
|
||||
thisObject.container.frame.width = FRAME_WIDTH
|
||||
thisObject.container.frame.height = FRAME_HEIGHT
|
||||
@@ -191,7 +156,7 @@ function newUiObjectTitle () {
|
||||
if (thisObject.editMode === true) {
|
||||
let inputPosition = {
|
||||
x: 0,
|
||||
y: 0 + CURRENT_TOP_MARGIN
|
||||
y: 0 + CURRENT_TOP_MARGIN + Y_OFFSET
|
||||
}
|
||||
|
||||
inputPosition = thisObject.container.frame.frameThisPoint(inputPosition)
|
||||
@@ -213,6 +178,9 @@ function newUiObjectTitle () {
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(thisObject.payload.node.type)
|
||||
if (nodeDefinition.title !== undefined) { return }
|
||||
|
||||
let checkPoint = {
|
||||
x: 0,
|
||||
y: 0
|
||||
@@ -252,7 +220,7 @@ function newUiObjectTitle () {
|
||||
}
|
||||
}
|
||||
|
||||
input.style = 'resize: none; border: none; outline: none; box-shadow: none; overflow:hidden; font-family: Saira; font-size: ' + fontSize + 'px; background-color: rgb(' + backgroundColor + ');color:rgb(255, 255, 255); width: ' + WIDTH + 'px; height: ' + HEIGHT + 'px'
|
||||
input.style = 'resize: none; border: none; outline: none; box-shadow: none; overflow:hidden; font-family: Saira Condensed; font-size: ' + fontSize + 'px; background-color: rgb(' + backgroundColor + ');color:rgb(255, 255, 255); width: ' + WIDTH + 'px; height: ' + HEIGHT + 'px'
|
||||
input.style.display = 'block'
|
||||
input.focus()
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ function newFrame () {
|
||||
containerName: '', // This is for debugging purposes only.
|
||||
parentFrame: undefined, // Here we store the parent cointainer zoom object.
|
||||
radius: 0,
|
||||
offset: undefined,
|
||||
position: undefined,
|
||||
container: undefined,
|
||||
width: browserCanvas.width,
|
||||
@@ -20,21 +21,30 @@ function newFrame () {
|
||||
isThisPointHere: isThisPointHere, // This function return true is the point received as parameter lives within this frame.
|
||||
isThisScreenPointHere: isThisScreenPointHere,
|
||||
isInViewPort: isInViewPort,
|
||||
canYouMoveHere: canYouMoveHere,
|
||||
initialize: initialize
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.parentFrame = undefined
|
||||
thisObject.position = undefined
|
||||
thisObject.offset = undefined
|
||||
}
|
||||
|
||||
function initialize (pType) {
|
||||
if (pType !== undefined) { thisObject.type = pType }
|
||||
|
||||
let position = {
|
||||
thisObject.position = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.position = position
|
||||
thisObject.offset = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
|
||||
function getBodyHeight () {
|
||||
@@ -42,7 +52,7 @@ function newFrame () {
|
||||
}
|
||||
|
||||
function isInViewPort () {
|
||||
/* This function is usefull to know if the object who has this frame is currently appearing at least in part at the viewPort */
|
||||
/* This function is usefull to know if the object who has this frame is currently appearing at least in part at the canvas.chartSpace.viewport */
|
||||
|
||||
point1 = {
|
||||
x: 0,
|
||||
@@ -59,7 +69,7 @@ function newFrame () {
|
||||
point1 = transformThisPoint(point1, thisObject.container)
|
||||
point3 = transformThisPoint(point3, thisObject.container)
|
||||
|
||||
if (point1.x < viewPort.visibleArea.topRight.x && point1.y < viewPort.visibleArea.bottomRight.y && point3.x > viewPort.visibleArea.bottomLeft.x && point3.y > viewPort.visibleArea.topLeft.y) {
|
||||
if (point1.x < canvas.chartSpace.viewport.visibleArea.topRight.x && point1.y < canvas.chartSpace.viewport.visibleArea.bottomRight.y && point3.x > canvas.chartSpace.viewport.visibleArea.bottomLeft.x && point3.y > canvas.chartSpace.viewport.visibleArea.topLeft.y) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@@ -87,11 +97,11 @@ function newFrame () {
|
||||
if (thisObject.parentFrame !== undefined) {
|
||||
parentPoint = thisObject.parentFrame.frameThisPoint(checkPoint)
|
||||
|
||||
returnPoint.x = parentPoint.x + thisObject.position.x
|
||||
returnPoint.y = parentPoint.y + thisObject.position.y
|
||||
returnPoint.x = parentPoint.x + thisObject.position.x + thisObject.offset.x
|
||||
returnPoint.y = parentPoint.y + thisObject.position.y + thisObject.offset.y
|
||||
} else {
|
||||
returnPoint.x = checkPoint.x + thisObject.position.x
|
||||
returnPoint.y = checkPoint.y + thisObject.position.y
|
||||
returnPoint.x = checkPoint.x + thisObject.position.x + thisObject.offset.x
|
||||
returnPoint.y = checkPoint.y + thisObject.position.y + thisObject.offset.y
|
||||
}
|
||||
|
||||
return returnPoint
|
||||
@@ -150,78 +160,6 @@ function newFrame () {
|
||||
return point
|
||||
}
|
||||
|
||||
function canYouMoveHere (tempDisplacement) {
|
||||
/*
|
||||
|
||||
The current frame has a position and a displacement. We need to check that none of the boundaries points of the frame fall outside of its container frame.
|
||||
First we apply the theoreticall displacement.
|
||||
|
||||
*/
|
||||
|
||||
point1 = {
|
||||
x: thisObject.position.x,
|
||||
y: thisObject.position.y
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: thisObject.position.x + thisObject.width,
|
||||
y: thisObject.position.y
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: thisObject.position.x + thisObject.width,
|
||||
y: thisObject.position.y + thisObject.height
|
||||
}
|
||||
|
||||
point4 = {
|
||||
x: thisObject.position.x,
|
||||
y: thisObject.position.y + thisObject.height
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
|
||||
if (thisObject.parentFrame !== undefined) {
|
||||
// If there is not a parent then there is no point to check bounderies.
|
||||
|
||||
point1 = thisObject.parentFrame.frameThisPoint(point1)
|
||||
point2 = thisObject.parentFrame.frameThisPoint(point2)
|
||||
point3 = thisObject.parentFrame.frameThisPoint(point3)
|
||||
point4 = thisObject.parentFrame.frameThisPoint(point4)
|
||||
|
||||
/* We apply the temporary displacement. */
|
||||
|
||||
point1 = tempDisplacement.displaceThisPoint(point1)
|
||||
point2 = tempDisplacement.displaceThisPoint(point2)
|
||||
point3 = tempDisplacement.displaceThisPoint(point3)
|
||||
point4 = tempDisplacement.displaceThisPoint(point4)
|
||||
|
||||
/* We add the actual displacement. */
|
||||
|
||||
point1 = thisObject.container.displacement.displaceThisPoint(point1)
|
||||
point2 = thisObject.container.displacement.displaceThisPoint(point2)
|
||||
point3 = thisObject.container.displacement.displaceThisPoint(point3)
|
||||
point4 = thisObject.container.displacement.displaceThisPoint(point4)
|
||||
|
||||
if (thisObject.parentFrame.isThisPointHere(point1) === false) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (thisObject.parentFrame.isThisPointHere(point2) === false) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (thisObject.parentFrame.isThisPointHere(point3) === false) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (thisObject.parentFrame.isThisPointHere(point4) === false) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
function isThisPointHere (point, outsideViewPort, dontTransform) {
|
||||
// The second parameter is usefull when you want to check a point that you already know is outside the viewport.
|
||||
|
||||
@@ -236,7 +174,6 @@ function newFrame () {
|
||||
in order to have the point on the containers coordinate system and be able to compare it with its dimmensions. */
|
||||
if (dontTransform === false || dontTransform === undefined) {
|
||||
if (outsideViewPort === true) {
|
||||
checkPoint = thisObject.container.displacement.undisplaceThisPoint(checkPoint)
|
||||
checkPoint = thisObject.container.frame.unframeThisPoint(checkPoint)
|
||||
} else {
|
||||
checkPoint = unTransformThisPoint(checkPoint, thisObject.container)
|
||||
@@ -275,7 +212,9 @@ function newFrame () {
|
||||
y: thisObject.position.y
|
||||
}
|
||||
|
||||
thisPoint = thisObject.parentFrame.frameThisPoint(thisPoint)
|
||||
if (thisObject.parentFrame !== undefined) {
|
||||
thisPoint = thisObject.parentFrame.frameThisPoint(thisPoint)
|
||||
}
|
||||
|
||||
/* Now we check if the resulting point is whin the current Frame. */
|
||||
|
||||
@@ -298,9 +237,9 @@ function newFrame () {
|
||||
}
|
||||
}
|
||||
|
||||
function draw (drawGrid, drawBorders, drawBackground, fitFunction) {
|
||||
function draw (drawGrid, drawBorders, drawBackground, fitFunction, style) {
|
||||
if (drawBorders === true) {
|
||||
borders(fitFunction)
|
||||
borders(fitFunction, style)
|
||||
}
|
||||
|
||||
if (drawGrid === true) {
|
||||
@@ -362,6 +301,7 @@ function newFrame () {
|
||||
|
||||
browserCanvasContext.lineWidth = 0.1
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + UI_COLOR.MANGANESE_PURPLE + ', 0.75)'
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
/* print the title */
|
||||
@@ -391,7 +331,7 @@ function newFrame () {
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
|
||||
function borders (fitFunction) {
|
||||
function borders (fitFunction, style) {
|
||||
/* Lest get the important points of the drawing so as to apply the needed transformations. */
|
||||
|
||||
let point1
|
||||
@@ -419,8 +359,7 @@ function newFrame () {
|
||||
y: thisObject.height
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
|
||||
/* Now the transformations. */
|
||||
point1 = transformThisPoint(point1, thisObject.container)
|
||||
point2 = transformThisPoint(point2, thisObject.container)
|
||||
point3 = transformThisPoint(point3, thisObject.container)
|
||||
@@ -433,8 +372,7 @@ function newFrame () {
|
||||
point4 = fitFunction(point4)
|
||||
}
|
||||
|
||||
/* Lets start the drawing. */
|
||||
|
||||
/* Lets start the drawing. */
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
@@ -443,8 +381,9 @@ function newFrame () {
|
||||
browserCanvasContext.lineTo(point1.x, point1.y)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(150, 150, 150, 1)'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + style.color + ', ' + style.opacity + ')'
|
||||
browserCanvasContext.lineWidth = style.lineWidth
|
||||
browserCanvasContext.setLineDash(style.lineDash)
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
browserCanvasContext.closePath()
|
||||
@@ -506,6 +445,7 @@ function newFrame () {
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(150, 150, 150, 0.1)'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
|
||||
@@ -563,6 +503,7 @@ function newFrame () {
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.strokeStyle = 'rgba(100, 100, 100, 0.2)'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.setLineDash([0, 0])
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
}
|
||||
+36
-46
@@ -1,20 +1,19 @@
|
||||
|
||||
/* User Interface Colors */
|
||||
|
||||
const STORAGE_PROVIDER = 'AAWeb';
|
||||
const CANVAS_APP_NAME = 'Canvas App'
|
||||
|
||||
const SUPPORTED_EXCHANGES = ["Poloniex"];
|
||||
const SUPPORTED_MARKETS = [
|
||||
{
|
||||
assetA: "USDT",
|
||||
assetB: "BTC",
|
||||
baseAsset: "USDT",
|
||||
quotedAsset: "BTC",
|
||||
}
|
||||
];
|
||||
const DEFAULT_EXCHANGE = "Poloniex";
|
||||
const DEFAULT_MARKET = {
|
||||
assetA: "USDT",
|
||||
assetB: "BTC",
|
||||
baseAsset: "USDT",
|
||||
quotedAsset: "BTC",
|
||||
};
|
||||
|
||||
UI_COLOR = {
|
||||
@@ -38,17 +37,35 @@ UI_COLOR = {
|
||||
/* User Interface Fonts */
|
||||
|
||||
UI_FONT = {
|
||||
PRIMARY: "Saira",
|
||||
PRIMARY: "Saira Condensed",
|
||||
SECONDARY: "Source Code Pro"
|
||||
};
|
||||
|
||||
FONT_ASPECT_RATIO = 0.45;
|
||||
const MIN_ZOOM_LEVEL = -28.25
|
||||
let FONT_ASPECT_RATIO = 0.32;
|
||||
|
||||
|
||||
const GET_CONTAINER_PURPOSE = {
|
||||
MOUSE_OVER: 1,
|
||||
MOUSE_WHEEL: 2,
|
||||
MOUSE_CLICK: 3
|
||||
MOUSE_CLICK: 3,
|
||||
DRAGGING: 4
|
||||
}
|
||||
|
||||
const ANGLE_TO_PARENT = {
|
||||
NOT_FIXED: 0,
|
||||
RANGE_360: 1,
|
||||
RANGE_180: 2,
|
||||
RANGE_90: 3,
|
||||
RANGE_45: 4
|
||||
}
|
||||
|
||||
const DISTANCE_TO_PARENT = {
|
||||
NOT_FIXED: 0,
|
||||
PARENT_025X: 1,
|
||||
PARENT_050X: 2,
|
||||
PARENT_100X: 3,
|
||||
PARENT_150X: 4,
|
||||
PARENT_200X: 5
|
||||
}
|
||||
|
||||
/* User Interface Panels */
|
||||
@@ -57,11 +74,13 @@ UI_PANEL = {
|
||||
WIDTH: {
|
||||
SMALL: 100,
|
||||
NORMAL: 150,
|
||||
MEDIUM: 200,
|
||||
LARGE: 250,
|
||||
X_LARGE: 350
|
||||
},
|
||||
HEIGHT: {
|
||||
SMALL: 65,
|
||||
MEDIUM: 90,
|
||||
NORMAL: 300,
|
||||
LARGE: 450
|
||||
}
|
||||
@@ -97,31 +116,6 @@ let dailyFilePeriods =
|
||||
|
||||
dailyFilePeriods = JSON.parse(dailyFilePeriods);
|
||||
|
||||
function convertTimePeriodToName(pTimePeriod) {
|
||||
|
||||
for (let i = 0; i < dailyFilePeriods.length; i++) {
|
||||
|
||||
let period = dailyFilePeriods[i];
|
||||
|
||||
if (period[0] === pTimePeriod) {
|
||||
|
||||
return period[1];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < marketFilesPeriods.length; i++) {
|
||||
|
||||
let period = marketFilesPeriods[i];
|
||||
|
||||
if (period[0] === pTimePeriod) {
|
||||
|
||||
return period[1];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.AT_BREAKPOINT = false;
|
||||
|
||||
let testUser = window.localStorage.getItem("test_user")
|
||||
@@ -140,7 +134,7 @@ const DEFAULT_CONFIG_TEXT = '// Write your config here'
|
||||
const DEFAULT_FORMULA_TEXT = '// Write your formula here'
|
||||
const DEFAULT_CODE_TEXT = '// Write your code here'
|
||||
|
||||
const USDT_BTC_HTH = 19900; // This is needed to know the scale of the market time line.
|
||||
const MAX_DEFAULT_RATE_SCALE_VALUE = 35000; // This is needed to know the scale of the market time line.
|
||||
|
||||
const WIDHTER_VOLUME_BAR_BASE_FACTOR = 2.5;
|
||||
const LESS_WIDHTER_VOLUME_BAR_TOP_FACTOR = 1 / 4;
|
||||
@@ -166,9 +160,9 @@ const _3_MINUTES_IN_MILISECONDS = 3 * 60 * 1000;
|
||||
const _2_MINUTES_IN_MILISECONDS = 2 * 60 * 1000;
|
||||
const _1_MINUTE_IN_MILISECONDS = 1 * 60 * 1000;
|
||||
|
||||
let NEW_SESSION_INITIAL_DATE = new Date(); // This value will be overwritten at the viewPort.initialize if the user had a prevous session with this same browser.
|
||||
let NEW_SESSION_INITIAL_DATE = new Date(); // This value will be overwritten at the canvas.chartSpace.viewport.initialize if the user had a prevous session with this same browser.
|
||||
let INITIAL_ZOOM_LEVEL = -28.25 // This is the zoom level at the view port in which the APP starts.
|
||||
let INITIAL_TIME_PERIOD = ONE_DAY_IN_MILISECONDS // This value will be overwritten at the viewPort.initialize if the user had a prevous session with this same browser.
|
||||
let INITIAL_TIME_PERIOD = ONE_DAY_IN_MILISECONDS // This value will be overwritten at the canvas.chartSpace.viewport.initialize if the user had a prevous session with this same browser.
|
||||
let VERY_LARGE_NUMBER = 100000000000
|
||||
|
||||
let CURRENT_TOP_MARGIN = window.canvasApp.topMargin
|
||||
@@ -181,13 +175,13 @@ maxDate.setDate(maxDate.getDate() + 365 * 1); // We might have charts that proj
|
||||
const MIN_PLOTABLE_DATE = new Date(2015, 0, 1, 0, 0, 0);
|
||||
const MAX_PLOTABLE_DATE = maxDate;
|
||||
|
||||
const TOP_SPACE_HEIGHT = 5;
|
||||
const COCKPIT_SPACE_HEIGHT = 40;
|
||||
const TOP_SPACE_HEIGHT = 2
|
||||
const COCKPIT_SPACE_HEIGHT = 30;
|
||||
const BREAKPOINT_HEIGHT = 15;
|
||||
const SIDE_PANEL_WIDTH = 450
|
||||
let COCKPIT_SPACE_POSITION = browserCanvas.height - COCKPIT_SPACE_HEIGHT
|
||||
|
||||
const PRODUCT_CARD_STATUS = {
|
||||
const LAYER_STATUS = {
|
||||
ON: 'on',
|
||||
LOADING: 'loading',
|
||||
OFF: 'off'
|
||||
@@ -207,16 +201,12 @@ const PERIOD_10_MIN = "10-min";
|
||||
const PERIOD_05_MIN = "05-min";
|
||||
const PERIOD_01_MIN = "01-min";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
We define here the size of the chartSpace. It has to bee enough big in order to accomodate all the charts we expect to display in this space.
|
||||
*/
|
||||
|
||||
const TIME_MACHINE_WIDTH = browserCanvas.width * 1000;
|
||||
const TIME_MACHINE_HEIGHT = browserCanvas.height * 100;
|
||||
const TIME_MACHINE_WIDTH = 250;
|
||||
const TIME_MACHINE_HEIGHT = 250 / 50;
|
||||
|
||||
function toRadians(angle) {
|
||||
return angle * (Math.PI / 180);
|
||||
|
||||
+531
@@ -0,0 +1,531 @@
|
||||
function newLayer () {
|
||||
const MODULE_NAME = 'Layer'
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
status: LAYER_STATUS.OFF,
|
||||
fitFunction: undefined,
|
||||
payload: undefined,
|
||||
definition: undefined,
|
||||
panels: undefined,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
turnOff: turnOff,
|
||||
turnOn: turnOn,
|
||||
setDatetime: setDatetime,
|
||||
setTimeFrame: setTimeFrame,
|
||||
onMarketFileLoaded: onMarketFileLoaded,
|
||||
onDailyFileLoaded: onDailyFileLoaded,
|
||||
onSingleFileLoaded: onSingleFileLoaded,
|
||||
onFileSequenceLoaded: onFileSequenceLoaded,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let LOADING_FILL_STYLE = 'rgba(234, 143, 23, @Opacity)'
|
||||
let LOADED_FILL_STYLE = 'rgba(45, 232, 28, @Opacity)'
|
||||
let UNLOADED_FILL_STYLE = 'rgba(226, 226, 226, @Opacity)'
|
||||
|
||||
let LOADING_STROKE_STYLE = 'rgba(234, 143, 23, @Opacity)'
|
||||
let LOADED_STROKE_STYLE = 'rgba(45, 232, 28, @Opacity)'
|
||||
let UNLOADED_STROKE_STYLE = 'rgba(226, 226, 226, @Opacity)'
|
||||
|
||||
let marketFileProgressBar = {
|
||||
value: 0,
|
||||
animatedValue: 0,
|
||||
fillStyle: UNLOADED_FILL_STYLE,
|
||||
strokeStyle: UNLOADED_STROKE_STYLE,
|
||||
opacity: 0.00
|
||||
}
|
||||
|
||||
let dailyFileProgressBar = {
|
||||
value: 0,
|
||||
animatedValue: 0,
|
||||
fillStyle: UNLOADED_FILL_STYLE,
|
||||
strokeStyle: UNLOADED_STROKE_STYLE,
|
||||
opacity: 0.00
|
||||
}
|
||||
|
||||
let singleFileProgressBar = {
|
||||
value: 0,
|
||||
animatedValue: 0,
|
||||
fillStyle: UNLOADED_FILL_STYLE,
|
||||
strokeStyle: UNLOADED_STROKE_STYLE,
|
||||
opacity: 0.00
|
||||
}
|
||||
|
||||
let fileSequenceProgressBar = {
|
||||
value: 0,
|
||||
animatedValue: 0,
|
||||
fillStyle: UNLOADED_FILL_STYLE,
|
||||
strokeStyle: UNLOADED_STROKE_STYLE,
|
||||
opacity: 0.00
|
||||
}
|
||||
|
||||
let timeFrame = INITIAL_TIME_PERIOD
|
||||
let datetime = NEW_SESSION_INITIAL_DATE
|
||||
|
||||
/* Add an Event Handler */
|
||||
|
||||
thisObject.eventHandler = newEventHandler()
|
||||
let imagesLoaded = 0
|
||||
let onMouseClickEventSuscriptionId
|
||||
let panelsVisibleButton
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.finalize()
|
||||
thisObject.eventHandler.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.eventHandler = undefined
|
||||
thisObject.status = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.payload = undefined
|
||||
thisObject.definition = undefined
|
||||
thisObject.panels = undefined
|
||||
|
||||
timeFrame = undefined
|
||||
datetime = undefined
|
||||
|
||||
LOADING_FILL_STYLE = undefined
|
||||
LOADED_FILL_STYLE = undefined
|
||||
UNLOADED_FILL_STYLE = undefined
|
||||
|
||||
LOADING_STROKE_STYLE = undefined
|
||||
LOADED_STROKE_STYLE = undefined
|
||||
UNLOADED_STROKE_STYLE = undefined
|
||||
|
||||
marketFileProgressBar = undefined
|
||||
dailyFileProgressBar = undefined
|
||||
singleFileProgressBar = undefined
|
||||
fileSequenceProgressBar = undefined
|
||||
|
||||
panelsVisibleButton = undefined
|
||||
|
||||
thisObject.container.eventHandler.stopListening(onMouseClickEventSuscriptionId)
|
||||
}
|
||||
|
||||
function initialize (callBackFunction) {
|
||||
/* Create this objects continer */
|
||||
try {
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME + ' ' + thisObject.payload.node.id)
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.isClickeable = true
|
||||
|
||||
/* Lets set the basic dimensions of this thisObject. */
|
||||
let position = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL
|
||||
thisObject.container.frame.height = 70
|
||||
|
||||
let functionLibraryProtocolNode = newProtocolNode()
|
||||
let lightingPath =
|
||||
'->Layer->' +
|
||||
'Data Product->Single Market Data->' +
|
||||
'Session Independent Data->Session Based Data->' +
|
||||
'Session Reference->Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->' +
|
||||
'Market->Market Base Asset->Asset->' +
|
||||
'Market Quoted Asset->Asset->' +
|
||||
'Exchange Markets->Crypto Exchange->' +
|
||||
'Product Definition->' +
|
||||
'Sensor Bot->Indicator Bot->Trading Bot->' +
|
||||
'Data Mine->' +
|
||||
'Dataset Definition->' +
|
||||
'Record Definition->Record Property->Formula->' +
|
||||
'Data Building Procedure->Procedure Loop->Javascript Code->Procedure Initialization->Javascript Code->' +
|
||||
'Calculations Procedure->Procedure Loop->Javascript Code->Procedure Initialization->Javascript Code->' +
|
||||
'Plotter Module->Plotter->' +
|
||||
'Shapes->' +
|
||||
'Chart Points->Point->Point Formula->' +
|
||||
'Polygon->Polygon Body->Style->Style Condition->Style->' +
|
||||
'Polygon Border->Style->Style Condition->Style->' +
|
||||
'Polygon Vertex->Point->' +
|
||||
'Plotter Panel->Javascript Code->Panel Data->Data Formula->'
|
||||
thisObject.definition = functionLibraryProtocolNode.getProtocolNode(thisObject.payload.node, false, true, true, false, false, lightingPath)
|
||||
|
||||
/* Here we validate that we have all the needed information */
|
||||
if (thisObject.definition.referenceParent === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.parentNode === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.parentNode.referenceParent === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.parentNode.referenceParent.parentNode === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.parentNode.referenceParent.parentNode.parentNode === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.parentNode.referenceParent.baseAsset === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.parentNode.referenceParent.baseAsset.referenceParent === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.parentNode.referenceParent.quotedAsset === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.parentNode.referenceParent.quotedAsset.referenceParent === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.referenceParent === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.referenceParent.parentNode === undefined) { return }
|
||||
if (thisObject.definition.referenceParent.referenceParent.parentNode.parentNode === undefined) { return }
|
||||
|
||||
/* Lets listen to our own events to react when we have a Mouse Click */
|
||||
onMouseClickEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
|
||||
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE)
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (panelsVisibleButton !== undefined) {
|
||||
let container = panelsVisibleButton.getContainer(point)
|
||||
if (container !== undefined) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
}
|
||||
}
|
||||
|
||||
function setDatetime (pDatetime) {
|
||||
/*
|
||||
When the datetime changes from one day to another, this forces cursors to potentially load more files, thus we reset this counter and
|
||||
get ready to receive events on files loaded.
|
||||
*/
|
||||
let currentDate = Math.trunc(datetime.valueOf() / ONE_DAY_IN_MILISECONDS)
|
||||
let newDate = Math.trunc(pDatetime.valueOf() / ONE_DAY_IN_MILISECONDS)
|
||||
|
||||
datetime = pDatetime
|
||||
|
||||
if (currentDate !== newDate) {
|
||||
if (timeFrame <= _1_HOUR_IN_MILISECONDS) {
|
||||
dailyFileProgressBar.animatedValue = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setTimeFrame (pTimeFrame) {
|
||||
/*
|
||||
When the time period below or equal to 1 hour changes, this forces cursors to potentially load more files, thus we reset this counter and
|
||||
get ready to receive events on files loaded.
|
||||
*/
|
||||
if (timeFrame !== pTimeFrame) {
|
||||
timeFrame = pTimeFrame
|
||||
|
||||
if (timeFrame <= _1_HOUR_IN_MILISECONDS) {
|
||||
dailyFileProgressBar.animatedValue = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMarketFileLoaded (event) {
|
||||
marketFileProgressBar.value = Math.trunc(event.totalValue * 100 / event.totalValue)
|
||||
marketFileProgressBar.fillStyle = LOADING_FILL_STYLE
|
||||
marketFileProgressBar.strokeStyle = LOADING_STROKE_STYLE
|
||||
|
||||
if (marketFileProgressBar.value > 100) { marketFileProgressBar.value = 100 }
|
||||
}
|
||||
|
||||
function onDailyFileLoaded (event) {
|
||||
dailyFileProgressBar.value = Math.trunc(event.currentValue * 100 / event.totalValue)
|
||||
dailyFileProgressBar.fillStyle = LOADING_FILL_STYLE
|
||||
dailyFileProgressBar.strokeStyle = LOADING_STROKE_STYLE
|
||||
|
||||
if (dailyFileProgressBar.value > 100) { dailyFileProgressBar.value = 100 }
|
||||
}
|
||||
|
||||
function onSingleFileLoaded (event) {
|
||||
singleFileProgressBar.value = Math.trunc(event.currentValue * 100 / event.totalValue)
|
||||
singleFileProgressBar.fillStyle = LOADING_FILL_STYLE
|
||||
singleFileProgressBar.strokeStyle = LOADING_STROKE_STYLE
|
||||
|
||||
if (singleFileProgressBar.value > 100) { singleFileProgressBar.value = 100 }
|
||||
}
|
||||
|
||||
function onFileSequenceLoaded (event) {
|
||||
fileSequenceProgressBar.value = Math.trunc(event.currentValue * 100 / event.totalValue)
|
||||
fileSequenceProgressBar.fillStyle = LOADING_FILL_STYLE
|
||||
fileSequenceProgressBar.strokeStyle = LOADING_STROKE_STYLE
|
||||
|
||||
if (fileSequenceProgressBar.value > 100) { fileSequenceProgressBar.value = 100 }
|
||||
}
|
||||
|
||||
function turnOff () {
|
||||
if (thisObject.status !== LAYER_STATUS.OFF) {
|
||||
resetProgressBars()
|
||||
changeStatusTo(LAYER_STATUS.OFF)
|
||||
}
|
||||
}
|
||||
|
||||
function turnOn () {
|
||||
if (thisObject.status === LAYER_STATUS.OFF) {
|
||||
resetProgressBars()
|
||||
changeStatusTo(LAYER_STATUS.LOADING)
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
switch (thisObject.status) {
|
||||
case LAYER_STATUS.ON:
|
||||
resetProgressBars()
|
||||
changeStatusTo(LAYER_STATUS.OFF)
|
||||
break
|
||||
case LAYER_STATUS.OFF:
|
||||
resetProgressBars()
|
||||
changeStatusTo(LAYER_STATUS.LOADING)
|
||||
break
|
||||
case LAYER_STATUS.LOADING:
|
||||
changeStatusTo(LAYER_STATUS.OFF)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
function resetProgressBars () {
|
||||
marketFileProgressBar.animatedValue = 0
|
||||
marketFileProgressBar.value = 0
|
||||
marketFileProgressBar.fillStyle = UNLOADED_FILL_STYLE
|
||||
marketFileProgressBar.strokeStyle = UNLOADED_STROKE_STYLE
|
||||
|
||||
dailyFileProgressBar.animatedValue = 0
|
||||
dailyFileProgressBar.value = 0
|
||||
dailyFileProgressBar.fillStyle = UNLOADED_FILL_STYLE
|
||||
dailyFileProgressBar.strokeStyle = UNLOADED_STROKE_STYLE
|
||||
|
||||
singleFileProgressBar.animatedValue = 0
|
||||
singleFileProgressBar.value = 0
|
||||
singleFileProgressBar.fillStyle = UNLOADED_FILL_STYLE
|
||||
singleFileProgressBar.strokeStyle = UNLOADED_STROKE_STYLE
|
||||
|
||||
fileSequenceProgressBar.animatedValue = 0
|
||||
fileSequenceProgressBar.value = 0
|
||||
fileSequenceProgressBar.fillStyle = UNLOADED_FILL_STYLE
|
||||
fileSequenceProgressBar.strokeStyle = UNLOADED_STROKE_STYLE
|
||||
}
|
||||
|
||||
function physics () {
|
||||
statusPhysics()
|
||||
childrenPhysics()
|
||||
}
|
||||
|
||||
function childrenPhysics () {
|
||||
/* Panels Visible Button Setup */
|
||||
if (thisObject.status === LAYER_STATUS.ON) {
|
||||
if (panelsVisibleButton === undefined) {
|
||||
if (thisObject.panels !== undefined) {
|
||||
if (thisObject.panels.length > 0) {
|
||||
panelsVisibleButton = newPanelsVisibleButton()
|
||||
|
||||
let storedValue = loadPropertyFromNodeConfig(thisObject.payload, 'showPanels')
|
||||
if (storedValue !== undefined) {
|
||||
if (storedValue === true || storedValue === false) {
|
||||
panelsVisibleButton.showPanels = storedValue
|
||||
}
|
||||
}
|
||||
|
||||
panelsVisibleButton.initialize(thisObject.panels)
|
||||
panelsVisibleButton.container.connectToParent(thisObject.container)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
savePropertyAtNodeConfig(thisObject.payload, 'showPanels', panelsVisibleButton.showPanels)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function statusPhysics () {
|
||||
/* We retrieve the stored status at the config. */
|
||||
try {
|
||||
let storedValue = loadPropertyFromNodeConfig(thisObject.payload, 'status')
|
||||
|
||||
if (storedValue !== undefined) {
|
||||
if (storedValue !== thisObject.status) {
|
||||
if (storedValue === LAYER_STATUS.ON) {
|
||||
resetProgressBars()
|
||||
changeStatusTo(LAYER_STATUS.LOADING)
|
||||
}
|
||||
if (storedValue === LAYER_STATUS.OFF) {
|
||||
resetProgressBars()
|
||||
changeStatusTo(LAYER_STATUS.OFF)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resetProgressBars()
|
||||
changeStatusTo(LAYER_STATUS.OFF)
|
||||
}
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
|
||||
/* Check when the loading finishes */
|
||||
if (
|
||||
thisObject.status === LAYER_STATUS.LOADING &&
|
||||
marketFileProgressBar.value === 100 &&
|
||||
dailyFileProgressBar.value === 100
|
||||
) {
|
||||
changeStatusTo(LAYER_STATUS.ON)
|
||||
}
|
||||
}
|
||||
|
||||
function changeStatusTo (newStatus) {
|
||||
if (thisObject.status !== newStatus) {
|
||||
thisObject.status = newStatus
|
||||
|
||||
if (thisObject.status === LAYER_STATUS.OFF) {
|
||||
if (panelsVisibleButton !== undefined) {
|
||||
panelsVisibleButton.finalize()
|
||||
panelsVisibleButton = undefined
|
||||
}
|
||||
}
|
||||
|
||||
savePropertyAtNodeConfig(thisObject.payload, 'status', thisObject.status)
|
||||
let eventData = thisObject
|
||||
thisObject.container.eventHandler.raiseEvent('Status Changed', eventData)
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
drawLayer()
|
||||
if (panelsVisibleButton !== undefined) {
|
||||
panelsVisibleButton.draw()
|
||||
}
|
||||
}
|
||||
|
||||
function drawLayer () {
|
||||
drawLayerDisplay()
|
||||
}
|
||||
|
||||
function drawProgressBar (progressBar, lineWidth, offsetY) {
|
||||
const ANIMATED_INCREMENT = 5
|
||||
const OPACITY_INCREMENT = 0.01
|
||||
const OPACITY_MIN = 1
|
||||
|
||||
let point1
|
||||
let point2
|
||||
let horizontalMargin = 12
|
||||
|
||||
if (progressBar.value === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
/* Animate */
|
||||
if (progressBar.animatedValue < progressBar.value) {
|
||||
progressBar.animatedValue = progressBar.animatedValue + ANIMATED_INCREMENT
|
||||
progressBar.opacity = progressBar.opacity + OPACITY_INCREMENT
|
||||
}
|
||||
|
||||
if (progressBar.animatedValue >= 100) {
|
||||
progressBar.animatedValue = 100
|
||||
|
||||
progressBar.opacity = progressBar.opacity - OPACITY_INCREMENT
|
||||
if (progressBar.opacity < OPACITY_MIN) { progressBar.opacity = OPACITY_MIN }
|
||||
|
||||
progressBar.strokeStyle = LOADED_STROKE_STYLE.replace('@Opacity', progressBar.opacity.toString())
|
||||
}
|
||||
|
||||
point1 = {
|
||||
x: 0 + horizontalMargin,
|
||||
y: thisObject.container.frame.height + offsetY
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: (thisObject.container.frame.width - horizontalMargin * 2) * progressBar.animatedValue / 100 + horizontalMargin,
|
||||
y: thisObject.container.frame.height + offsetY
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
point1 = thisObject.container.frame.frameThisPoint(point1)
|
||||
point2 = thisObject.container.frame.frameThisPoint(point2)
|
||||
|
||||
point1 = thisObject.fitFunction(point1)
|
||||
point2 = thisObject.fitFunction(point2)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.strokeStyle = progressBar.strokeStyle.replace('@Opacity', progressBar.opacity.toString())
|
||||
|
||||
browserCanvasContext.setLineDash([1, 4])
|
||||
browserCanvasContext.lineWidth = lineWidth
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
|
||||
function drawLayerDisplay () {
|
||||
let baseAsset = thisObject.definition.referenceParent.parentNode.referenceParent.baseAsset.referenceParent
|
||||
let quotedAsset = thisObject.definition.referenceParent.parentNode.referenceParent.quotedAsset.referenceParent
|
||||
let market = baseAsset.code.codeName + '/' + quotedAsset.code.codeName
|
||||
let exchange = thisObject.definition.referenceParent.parentNode.referenceParent.parentNode.parentNode
|
||||
let plotterModule = thisObject.definition.referenceParent.referenceParent.referenceParent
|
||||
|
||||
let label1 = thisObject.payload.node.name
|
||||
let label2 = exchange.name.substring(0, 15) + ' - ' + market
|
||||
let label3 = thisObject.status.toUpperCase()
|
||||
|
||||
if (label1 !== undefined) {
|
||||
label1 = label1.substring(0, 22)
|
||||
}
|
||||
|
||||
let icon1 = getIcon(exchange)
|
||||
|
||||
let icon2
|
||||
if (plotterModule.code.icon !== undefined) {
|
||||
icon2 = canvas.designerSpace.iconCollection.get(plotterModule.code.icon)
|
||||
}
|
||||
|
||||
let icon3 = getIcon(baseAsset)
|
||||
let icon4 = getIcon(quotedAsset)
|
||||
|
||||
function getIcon (node) {
|
||||
let nodeDefinition = APP_SCHEMA_MAP.get(node.type)
|
||||
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) {
|
||||
iconName = alternativeIcon.iconName
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iconName !== undefined) {
|
||||
icon = canvas.designerSpace.iconCollection.get(iconName)
|
||||
} else {
|
||||
icon = canvas.designerSpace.iconCollection.get(nodeDefinition.icon)
|
||||
}
|
||||
return icon
|
||||
}
|
||||
|
||||
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, 17, thisObject.container)
|
||||
drawLabel(label2, 1 / 2, 8.2 / 10, -5, 0, 9, thisObject.container)
|
||||
drawLabel(label3, 1 / 2, 9.5 / 10, -5, 0, 9, thisObject.container)
|
||||
|
||||
drawProgressBar(marketFileProgressBar, 1, -45)
|
||||
drawProgressBar(dailyFileProgressBar, 1, -46)
|
||||
drawProgressBar(singleFileProgressBar, 1, -47)
|
||||
drawProgressBar(fileSequenceProgressBar, 1, -48)
|
||||
|
||||
drawIcon(icon1, 1 / 8, 2 / 10, 0, 0, 14, thisObject.container)
|
||||
drawIcon(icon2, 7 / 8, 2 / 10, 0, 0, 14, thisObject.container)
|
||||
drawIcon(icon3, 3.4 / 8, 2 / 10, 0, 0, 14, thisObject.container)
|
||||
drawIcon(icon4, 4.6 / 8, 2 / 10, 0, 0, 14, thisObject.container)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,456 @@
|
||||
function newLayersPanel () {
|
||||
let thisObject = {
|
||||
name: 'Layers Panel',
|
||||
fitFunction: undefined,
|
||||
container: undefined,
|
||||
layers: [],
|
||||
payload: undefined,
|
||||
isVisible: true,
|
||||
panelTabButton: undefined,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize()
|
||||
thisObject.container.isDraggeable = true
|
||||
thisObject.container.isWheelable = true
|
||||
|
||||
let isInitialized = false
|
||||
|
||||
let layersMap = new Map()
|
||||
let visibleLayers = []
|
||||
let firstVisibleLayer = 1
|
||||
|
||||
const LAYER_SEPARATION = 0
|
||||
|
||||
let visible = true
|
||||
let headerHeight = 40
|
||||
let footerHeight = 10
|
||||
let layerHeight = 70
|
||||
let desiredVisibleLayers = 5
|
||||
let posibleVisibleLayers = 5
|
||||
let desiredPanelHeight = (layerHeight + LAYER_SEPARATION) * desiredVisibleLayers + headerHeight + footerHeight
|
||||
let posiblePanelHeight = (layerHeight + LAYER_SEPARATION) * posibleVisibleLayers + headerHeight + footerHeight
|
||||
|
||||
let onMouseWheelEventSuscriptionId
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseWheelEventSuscriptionId)
|
||||
|
||||
thisObject.panelTabButton.finalize()
|
||||
thisObject.panelTabButton = undefined
|
||||
layersMap = undefined
|
||||
visibleLayers = undefined
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
|
||||
thisObject.payload = undefined
|
||||
thisObject = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.name = thisObject.payload.node.name
|
||||
thisObject.container.frame.containerName = thisObject.container.name
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL
|
||||
thisObject.container.frame.height = headerHeight
|
||||
|
||||
let position = { // Default position
|
||||
x: canvas.chartSpace.viewport.visibleArea.topLeft.x,
|
||||
y: canvas.chartSpace.viewport.visibleArea.topLeft.y
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
loadFrame(thisObject.payload, thisObject.container.frame)
|
||||
|
||||
thisObject.panelTabButton = newPanelTabButton()
|
||||
thisObject.panelTabButton.parentContainer = thisObject.container
|
||||
thisObject.panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
thisObject.panelTabButton.fitFunction = thisObject.fitFunction
|
||||
thisObject.panelTabButton.initialize()
|
||||
|
||||
onMouseWheelEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
|
||||
readObjectState()
|
||||
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
function saveObjectStateVisibleLayers () {
|
||||
savePropertyAtNodeConfig(thisObject.payload, 'visibleLayers', desiredVisibleLayers)
|
||||
}
|
||||
|
||||
function saveObjectStatePanelLocation () {
|
||||
savePropertyAtNodeConfig(thisObject.payload, 'panelLocation', thisObject.panelTabButton.status)
|
||||
}
|
||||
|
||||
function readObjectState () {
|
||||
let storedValue
|
||||
|
||||
storedValue = loadPropertyFromNodeConfig(thisObject.payload, 'visibleLayers')
|
||||
|
||||
if (isNaN(storedValue) || storedValue === null || storedValue === undefined) {
|
||||
// not using this value
|
||||
saveObjectStateVisibleLayers() // this overrides any invalid value at the config.
|
||||
return
|
||||
} else {
|
||||
if (storedValue < 0) { storedValue = 0 }
|
||||
if (storedValue > thisObject.layers.length) {
|
||||
storedValue = thisObject.layers.length
|
||||
}
|
||||
|
||||
if (storedValue !== desiredVisibleLayers) {
|
||||
desiredVisibleLayers = storedValue
|
||||
desiredPanelHeight = (layerHeight + LAYER_SEPARATION) * desiredVisibleLayers + headerHeight + footerHeight
|
||||
calculateVisbleLayers()
|
||||
}
|
||||
}
|
||||
|
||||
storedValue = loadPropertyFromNodeConfig(thisObject.payload, 'panelLocation')
|
||||
|
||||
if (storedValue === null || storedValue === undefined) {
|
||||
// not using this value
|
||||
saveObjectStatePanelLocation() // this overrides any invalid value at the config.
|
||||
return
|
||||
} else {
|
||||
if (storedValue !== 'up' && storedValue !== 'down') {
|
||||
saveObjectStatePanelLocation() // this overrides any invalid value at the config.
|
||||
return
|
||||
}
|
||||
thisObject.panelTabButton.setStatus(storedValue)
|
||||
saveObjectStatePanelLocation()
|
||||
}
|
||||
}
|
||||
|
||||
function removeLayer (id) {
|
||||
let layer = layersMap.get(id)
|
||||
layersMap.delete(id)
|
||||
layer.turnOff()
|
||||
layer.container.eventHandler.stopListening(layer.onLayerStatusChangedEventSuscriptionId)
|
||||
layer.container.eventHandler.stopListening(layer.onMouseWheelEventSuscriptionId)
|
||||
layer.finalize()
|
||||
}
|
||||
|
||||
function addLayer (layerNode) {
|
||||
/* Now we create Product objects */
|
||||
let layer = newLayer()
|
||||
layer.payload = layerNode.payload
|
||||
layer.nodeId = layerNode.payload.node.id
|
||||
layer.fitFunction = thisObject.fitFunction
|
||||
|
||||
/* Initialize it */
|
||||
layer.initialize(onInitialized)
|
||||
|
||||
function onInitialized (err) {
|
||||
if (err.result === GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
layersMap.set(layerNode.id, layer)
|
||||
|
||||
/* Container Stuff */
|
||||
layer.container.frame.parentFrame = thisObject.container.frame
|
||||
layer.container.parentContainer = thisObject.container
|
||||
layer.container.isWheelable = true
|
||||
|
||||
/* Add to the Product Array */
|
||||
thisObject.layers.push(layer)
|
||||
|
||||
/* Listen to Status Changes Events */
|
||||
layer.onLayerStatusChangedEventSuscriptionId = layer.container.eventHandler.listenToEvent('Status Changed', onLayerStatusChanged)
|
||||
layer.onMouseWheelEventSuscriptionId = layer.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
|
||||
return layer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 layer
|
||||
desiredVisibleLayers = desiredVisibleLayers + delta
|
||||
if (desiredVisibleLayers < 0) { desiredVisibleLayers = 0 }
|
||||
if (desiredVisibleLayers > thisObject.layers.length) { desiredVisibleLayers = thisObject.layers.length }
|
||||
} else {
|
||||
firstVisibleLayer = firstVisibleLayer + delta
|
||||
}
|
||||
desiredPanelHeight = (layerHeight + LAYER_SEPARATION) * desiredVisibleLayers + headerHeight + footerHeight
|
||||
calculateVisbleLayers()
|
||||
saveObjectStateVisibleLayers()
|
||||
}
|
||||
|
||||
function panelSizePhysics () {
|
||||
let viewPortHeight = canvas.chartSpace.viewport.visibleArea.bottomLeft.y - canvas.chartSpace.viewport.visibleArea.topLeft.y
|
||||
|
||||
if (viewPortHeight < headerHeight) {
|
||||
visible = false
|
||||
} else {
|
||||
visible = true
|
||||
}
|
||||
|
||||
if (desiredPanelHeight > viewPortHeight) {
|
||||
posibleVisibleLayers = Math.trunc((viewPortHeight - headerHeight - footerHeight) / (layerHeight + LAYER_SEPARATION))
|
||||
} else {
|
||||
posibleVisibleLayers = desiredVisibleLayers
|
||||
}
|
||||
if (thisObject.layers.length < posibleVisibleLayers) { posibleVisibleLayers = thisObject.layers.length }
|
||||
|
||||
if (posibleVisibleLayers === 0) {
|
||||
posiblePanelHeight = (layerHeight + LAYER_SEPARATION) * posibleVisibleLayers + headerHeight
|
||||
} else {
|
||||
posiblePanelHeight = (layerHeight + LAYER_SEPARATION) * posibleVisibleLayers + headerHeight + footerHeight
|
||||
}
|
||||
|
||||
thisObject.container.frame.height = posiblePanelHeight
|
||||
}
|
||||
|
||||
function calculateVisbleLayers () {
|
||||
panelSizePhysics()
|
||||
let availableSlots = posibleVisibleLayers
|
||||
|
||||
if (firstVisibleLayer < 1) { firstVisibleLayer = 1 }
|
||||
if (firstVisibleLayer > (thisObject.layers.length - availableSlots + 1)) { firstVisibleLayer = thisObject.layers.length - availableSlots + 1 }
|
||||
|
||||
visibleLayers = []
|
||||
|
||||
for (let i = 0; i < thisObject.layers.length; i++) {
|
||||
if (i + 1 >= firstVisibleLayer && i + 1 < firstVisibleLayer + availableSlots) {
|
||||
let layer = thisObject.layers[i]
|
||||
|
||||
layer.container.frame.position.x = 0
|
||||
layer.container.frame.position.y = (layerHeight + LAYER_SEPARATION) * visibleLayers.length + headerHeight
|
||||
|
||||
/* Add to Visible Product Array */
|
||||
visibleLayers.push(layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onLayerStatusChanged (layer) {
|
||||
thisObject.container.eventHandler.raiseEvent('Layer Status Changed', layer)
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
let container
|
||||
|
||||
container = thisObject.panelTabButton.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 < visibleLayers.length; i++) {
|
||||
container = visibleLayers[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) {
|
||||
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.layers.length; i++) {
|
||||
let layer = thisObject.layers[i]
|
||||
layer.physics()
|
||||
}
|
||||
}
|
||||
|
||||
function syncWithConfigPhysics () {
|
||||
readObjectState()
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (isInitialized === false) { return }
|
||||
thisObject.panelTabButton.physics()
|
||||
saveFrame(thisObject.payload, thisObject.container.frame)
|
||||
syncWithConfigPhysics()
|
||||
|
||||
/*
|
||||
The overall idea here is that we need to keep syncronized the panel with the layers that are
|
||||
defined at the Designer. Users can connect or disconnect any objext resulting in changes in which
|
||||
are valid layers and which not at any point in time. So what we do here is trying to keep the panel
|
||||
only with the layers that are connected to the Charting Space hiriarcy.
|
||||
|
||||
To achieve this, first we are going to move all session related cards to a local array. Then we are
|
||||
going to check for layers at the designer, and will move back the cards which still have layers well
|
||||
defined to where they were.
|
||||
|
||||
If we find new layers we will add them at that point. Finally, the cards that still remain at the
|
||||
local array after all the layers at the designer have been processed, are turned off and discarded.
|
||||
*/
|
||||
childrenPhysics()
|
||||
|
||||
let localLayers = []
|
||||
moveToLocalLayers()
|
||||
syncWithDesignerLayers()
|
||||
|
||||
/* At this poins all the cards still at the local array need to be removed from the panel. */
|
||||
turnOffUnusedLayers()
|
||||
calculateVisbleLayers()
|
||||
|
||||
function syncWithDesignerLayers () {
|
||||
let layerManager = thisObject.payload.node
|
||||
for (let p = 0; p < layerManager.layers.length; p++) {
|
||||
let layerNode = layerManager.layers[p]
|
||||
|
||||
let found = removeFromLocalLayers(layerNode.id)
|
||||
if (found !== true) {
|
||||
layer = addLayer(layerNode)
|
||||
if (layer !== undefined) {
|
||||
onLayerStatusChanged(layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function moveToLocalLayers () {
|
||||
removeNext()
|
||||
|
||||
function removeNext () {
|
||||
for (let i = 0; i < thisObject.layers.length; i++) {
|
||||
let layer = thisObject.layers[i]
|
||||
|
||||
thisObject.layers.splice(i, 1)
|
||||
localLayers.push(layer)
|
||||
removeNext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeFromLocalLayers (id) {
|
||||
for (let i = 0; i < localLayers.length; i++) {
|
||||
let layer = localLayers[i]
|
||||
if (layer.payload.node.id === id) {
|
||||
thisObject.layers.push(layer)
|
||||
localLayers.splice(i, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function turnOffUnusedLayers () {
|
||||
for (let i = 0; i < localLayers.length; i++) {
|
||||
let layer = localLayers[i]
|
||||
removeLayer(layer.nodeId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (isInitialized === false || visible === false) { return }
|
||||
|
||||
// thisObject.container.frame.draw(false, false, false, thisObject.fitFunction)
|
||||
|
||||
drawHeader()
|
||||
for (let i = 0; i < visibleLayers.length; i++) {
|
||||
visibleLayers[i].draw()
|
||||
}
|
||||
drawScrollBar()
|
||||
thisObject.panelTabButton.draw()
|
||||
}
|
||||
|
||||
function drawHeader () {
|
||||
let label1 = thisObject.payload.node.payload.parentNode.payload.parentNode.name.substring(0, 18)
|
||||
let label2 = thisObject.payload.node.payload.parentNode.name.substring(0, 18)
|
||||
let label3 = ''
|
||||
|
||||
let icon1 = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.payload.parentNode.type)
|
||||
let icon2 = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.type)
|
||||
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
|
||||
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)
|
||||
drawLabel(label2, 1 / 2, 0, 0, 30, 9, thisObject.container)
|
||||
|
||||
drawIcon(icon1, 1 / 8, 0, 0, 20, 28, thisObject.container)
|
||||
drawIcon(icon2, 7 / 8, 0, 0, 20, 28, thisObject.container)
|
||||
}
|
||||
|
||||
function drawScrollBar () {
|
||||
if (thisObject.layers.length > posibleVisibleLayers && posibleVisibleLayers > 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 = posibleVisibleLayers / thisObject.layers.length
|
||||
let handleHeight = (posibleVisibleLayers * (layerHeight + LAYER_SEPARATION)) * ratio
|
||||
let handleTopPoint = {
|
||||
x: thisObject.container.frame.width - xOffset,
|
||||
y: headerHeight + (layerHeight + LAYER_SEPARATION) * ratio * (firstVisibleLayer - 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
+101
-77
@@ -3,78 +3,121 @@ function newPanelTabButton () {
|
||||
container: undefined,
|
||||
fitFunction: undefined,
|
||||
parentContainer: undefined,
|
||||
status: undefined,
|
||||
setStatus: setStatus,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let isInitialized = false
|
||||
/* Cointainer stuff */
|
||||
|
||||
var container = newContainer()
|
||||
|
||||
container.name = 'Panel Tab Button'
|
||||
container.initialize()
|
||||
|
||||
container.isClickeable = true
|
||||
|
||||
thisObject.container = container
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.name = 'Panel Tab Button'
|
||||
thisObject.container.initialize()
|
||||
thisObject.container.isClickeable = true
|
||||
thisObject.container.frame.containerName = 'Panel Tab Button'
|
||||
|
||||
/* Lets listen to our own events to react when we have a Mouse Click */
|
||||
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseClick', buttonPressed)
|
||||
|
||||
/* Animation to hide the pannel */
|
||||
|
||||
let tabStatus = 'visible'
|
||||
let visiblePosition = {}
|
||||
let hiddenPosition = {}
|
||||
thisObject.status = 'up'
|
||||
let upPosition = {}
|
||||
let downPosition = {}
|
||||
let transitionPosition = {}
|
||||
|
||||
let onMouseClickEventSuscriptionId
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseClickEventSuscriptionId)
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.parentContainer = undefined
|
||||
|
||||
thisObject.status = undefined
|
||||
upPosition = undefined
|
||||
downPosition = undefined
|
||||
transitionPosition = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.frame.width = 10
|
||||
thisObject.container.frame.height = 10
|
||||
|
||||
var position = {
|
||||
x: thisObject.parentContainer.frame.width - 15,
|
||||
y: 2
|
||||
x: thisObject.parentContainer.frame.width - 14,
|
||||
y: 1
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
|
||||
visiblePosition.x = thisObject.parentContainer.frame.position.x
|
||||
visiblePosition.y = thisObject.parentContainer.frame.position.y
|
||||
upPosition.x = thisObject.parentContainer.frame.position.x
|
||||
upPosition.y = thisObject.parentContainer.frame.position.y
|
||||
|
||||
hiddenPosition.x = thisObject.parentContainer.frame.position.x
|
||||
hiddenPosition.y = viewPort.visibleArea.bottomRight.y
|
||||
downPosition.x = thisObject.parentContainer.frame.position.x
|
||||
downPosition.y = canvas.chartSpace.viewport.visibleArea.bottomRight.y
|
||||
|
||||
transitionPosition.x = visiblePosition.x
|
||||
transitionPosition.y = visiblePosition.y
|
||||
transitionPosition.x = upPosition.x
|
||||
transitionPosition.y = upPosition.y
|
||||
|
||||
/* Lets listen to our own events to react when we have a Mouse Click */
|
||||
onMouseClickEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
function buttonPressed (event) {
|
||||
if (tabStatus === 'visible') {
|
||||
visiblePosition.x = thisObject.parentContainer.frame.position.x
|
||||
visiblePosition.y = thisObject.parentContainer.frame.position.y
|
||||
function setStatus (value) {
|
||||
if (value === 'up' && thisObject.status === 'down') {
|
||||
thisObject.status = 'going up'
|
||||
}
|
||||
if (value === 'down' && thisObject.status === 'up') {
|
||||
thisObject.status = 'going down'
|
||||
}
|
||||
}
|
||||
|
||||
hiddenPosition.x = thisObject.parentContainer.frame.position.x
|
||||
hiddenPosition.y = viewPort.visibleArea.bottomRight.y
|
||||
function onMouseClick (event) {
|
||||
if (thisObject.status === 'up') {
|
||||
transitionPosition.x = upPosition.x
|
||||
transitionPosition.y = upPosition.y
|
||||
|
||||
transitionPosition.x = visiblePosition.x
|
||||
transitionPosition.y = visiblePosition.y
|
||||
|
||||
thisObject.parentContainer.isDraggeable = false
|
||||
thisObject.parentContainer.isWheelable = false
|
||||
tabStatus = 'going down'
|
||||
thisObject.status = 'going down'
|
||||
} else {
|
||||
thisObject.parentContainer.isDraggeable = true
|
||||
thisObject.parentContainer.isWheelable = true
|
||||
tabStatus = 'going up'
|
||||
transitionPosition.x = downPosition.x
|
||||
transitionPosition.y = downPosition.y
|
||||
|
||||
thisObject.status = 'going up'
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (isInitialized === false) { return }
|
||||
|
||||
upPosition.x = thisObject.parentContainer.frame.position.x
|
||||
upPosition.y = canvas.chartSpace.viewport.visibleArea.topRight.y
|
||||
|
||||
downPosition.x = thisObject.parentContainer.frame.position.x
|
||||
downPosition.y = canvas.chartSpace.viewport.visibleArea.bottomRight.y
|
||||
|
||||
if (thisObject.status === 'going down') {
|
||||
if (transitionPosition.y < downPosition.y) {
|
||||
transitionPosition.y = transitionPosition.y + 50
|
||||
thisObject.parentContainer.frame.position.y = transitionPosition.y
|
||||
} else {
|
||||
thisObject.parentContainer.frame.position.y = downPosition.y
|
||||
thisObject.status = 'down'
|
||||
}
|
||||
}
|
||||
if (thisObject.status === 'going up') {
|
||||
if (transitionPosition.y > upPosition.y) {
|
||||
transitionPosition.y = transitionPosition.y - 50
|
||||
thisObject.parentContainer.frame.position.y = transitionPosition.y
|
||||
} else {
|
||||
thisObject.parentContainer.frame.position.y = upPosition.y
|
||||
thisObject.status = 'up'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,29 +125,10 @@ function newPanelTabButton () {
|
||||
if (isInitialized === false) { return }
|
||||
|
||||
drawButton()
|
||||
|
||||
if (tabStatus === 'going down') {
|
||||
if (transitionPosition.y < hiddenPosition.y) {
|
||||
transitionPosition.y = transitionPosition.y + 50
|
||||
thisObject.parentContainer.frame.position.y = transitionPosition.y
|
||||
} else {
|
||||
thisObject.parentContainer.frame.position.y = hiddenPosition.y
|
||||
tabStatus = 'hidden'
|
||||
}
|
||||
}
|
||||
if (tabStatus === 'going up') {
|
||||
if (transitionPosition.y > visiblePosition.y) {
|
||||
transitionPosition.y = transitionPosition.y - 50
|
||||
thisObject.parentContainer.frame.position.y = transitionPosition.y
|
||||
} else {
|
||||
thisObject.parentContainer.frame.position.y = visiblePosition.y
|
||||
tabStatus = 'visible'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
var container
|
||||
let container
|
||||
|
||||
/* First we check if thisObject point is inside thisObject space. */
|
||||
|
||||
@@ -124,21 +148,21 @@ function newPanelTabButton () {
|
||||
let point2
|
||||
let point3
|
||||
|
||||
switch (tabStatus) {
|
||||
case 'visible': {
|
||||
switch (thisObject.status) {
|
||||
case 'up': {
|
||||
point1 = {
|
||||
x: 3,
|
||||
y: 3
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: container.frame.width - 3,
|
||||
x: thisObject.container.frame.width - 3,
|
||||
y: 3
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: container.frame.width / 2,
|
||||
y: container.frame.height - 3
|
||||
x: thisObject.container.frame.width / 2,
|
||||
y: thisObject.container.frame.height - 3
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -150,13 +174,13 @@ function newPanelTabButton () {
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: container.frame.width - 4,
|
||||
x: thisObject.container.frame.width - 4,
|
||||
y: 4
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: container.frame.width / 2,
|
||||
y: container.frame.height - 4
|
||||
x: thisObject.container.frame.width / 2,
|
||||
y: thisObject.container.frame.height - 4
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -164,34 +188,34 @@ function newPanelTabButton () {
|
||||
case 'going up': {
|
||||
point1 = {
|
||||
x: 4,
|
||||
y: container.frame.height - 4
|
||||
y: thisObject.container.frame.height - 4
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: container.frame.width - 4,
|
||||
y: container.frame.height - 4
|
||||
x: thisObject.container.frame.width - 4,
|
||||
y: thisObject.container.frame.height - 4
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: container.frame.width / 2,
|
||||
x: thisObject.container.frame.width / 2,
|
||||
y: 4
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'hidden': {
|
||||
case 'down': {
|
||||
point1 = {
|
||||
x: 3,
|
||||
y: container.frame.height - 3
|
||||
y: thisObject.container.frame.height - 3
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: container.frame.width - 3,
|
||||
y: container.frame.height - 3
|
||||
x: thisObject.container.frame.width - 3,
|
||||
y: thisObject.container.frame.height - 3
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: container.frame.width / 2,
|
||||
x: thisObject.container.frame.width / 2,
|
||||
y: 3
|
||||
}
|
||||
break
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
function newPanelsVisibleButton () {
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
fitFunction: undefined,
|
||||
parentContainer: undefined,
|
||||
panels: undefined,
|
||||
showPanels: true,
|
||||
draw: draw,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
/* Cointainer stuff */
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.name = 'Panels Visible Button'
|
||||
thisObject.container.initialize()
|
||||
thisObject.container.isClickeable = true
|
||||
thisObject.container.frame.containerName = 'Panels Visible Button'
|
||||
|
||||
let onMouseClickEventSuscriptionId
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseClickEventSuscriptionId)
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.parentContainer = undefined
|
||||
thisObject.panels = undefined
|
||||
}
|
||||
|
||||
function initialize (panels) {
|
||||
thisObject.panels = panels
|
||||
setPanelVisibility()
|
||||
|
||||
thisObject.container.frame.width = 25
|
||||
thisObject.container.frame.height = 25
|
||||
|
||||
let position = {
|
||||
x: thisObject.container.frame.width * 1 / 8,
|
||||
y: 45
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
|
||||
/* Lets listen to our own events to react when we have a Mouse Click */
|
||||
onMouseClickEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
if (thisObject.showPanels === false) {
|
||||
thisObject.showPanels = true
|
||||
} else {
|
||||
thisObject.showPanels = false
|
||||
}
|
||||
setPanelVisibility()
|
||||
}
|
||||
|
||||
function setPanelVisibility () {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
panel = canvas.panelsSpace.getPanel(thisObject.panels[i])
|
||||
panel.isVisible = thisObject.showPanels
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
let icon
|
||||
if (thisObject.showPanels === true) {
|
||||
icon = canvas.designerSpace.iconCollection.get('plotter-panel')
|
||||
} else {
|
||||
icon = canvas.designerSpace.iconCollection.get('social-bot')
|
||||
}
|
||||
|
||||
drawIcon(icon, 1 / 2, 1 / 2, 0, 0, 14, thisObject.container)
|
||||
}
|
||||
}
|
||||
+25
-12
@@ -8,18 +8,17 @@ function newPlotterPanel () {
|
||||
|
||||
let thisObject = {
|
||||
fitFunction: undefined,
|
||||
onRecordChange: onRecordChange,
|
||||
container: undefined,
|
||||
isVisible: true,
|
||||
onRecordChange: onRecordChange,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let container = newContainer()
|
||||
container.initialize()
|
||||
thisObject.container = container
|
||||
|
||||
container.frame.containerName = 'Plotter Panel'
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize('Plotter Panel')
|
||||
|
||||
let heightFactor = 1
|
||||
let currentRecord
|
||||
@@ -28,15 +27,28 @@ function newPlotterPanel () {
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.isVisible = undefined
|
||||
|
||||
heightFactor = undefined
|
||||
currentRecord = undefined
|
||||
panelTabButton.finalize()
|
||||
panelTabButton = undefined
|
||||
panelNode = undefined
|
||||
}
|
||||
|
||||
function initialize (pPanelNode) {
|
||||
panelNode = pPanelNode
|
||||
container.frame.containerName = panelNode.name
|
||||
thisObject.container.frame.containerName = panelNode.name
|
||||
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL
|
||||
thisObject.container.frame.height = UI_PANEL.HEIGHT.NORMAL
|
||||
|
||||
thisObject.container.frame.position.x = viewPort.visibleArea.topRight.x - thisObject.container.frame.width - thisObject.container.frame.width * Math.random() * 8
|
||||
thisObject.container.frame.position.y = viewPort.visibleArea.bottomLeft.y - thisObject.container.frame.height - thisObject.container.frame.height * Math.random() * 1.5
|
||||
thisObject.container.frame.position.x = canvas.chartSpace.viewport.visibleArea.topRight.x - thisObject.container.frame.width - thisObject.container.frame.width * Math.random() * 8
|
||||
thisObject.container.frame.position.y = canvas.chartSpace.viewport.visibleArea.bottomLeft.y - thisObject.container.frame.height - thisObject.container.frame.height * Math.random() * 1.5
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
@@ -46,6 +58,7 @@ function newPlotterPanel () {
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
let container
|
||||
|
||||
container = panelTabButton.getContainer(point)
|
||||
@@ -70,10 +83,10 @@ function newPlotterPanel () {
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (thisObject.isVisible !== true) { return }
|
||||
|
||||
thisObject.container.frame.draw(false, false, true, thisObject.fitFunction)
|
||||
|
||||
plotCurrentRecordData()
|
||||
|
||||
panelTabButton.draw()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,967 +0,0 @@
|
||||
function newProductCard () {
|
||||
const MODULE_NAME = 'Product Card'
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
status: PRODUCT_CARD_STATUS.OFF,
|
||||
devTeam: undefined,
|
||||
bot: undefined,
|
||||
product: undefined,
|
||||
code: undefined,
|
||||
fitFunction: undefined,
|
||||
draw: draw,
|
||||
turnOff: turnOff,
|
||||
turnOn: turnOn,
|
||||
setDatetime: setDatetime,
|
||||
setTimePeriod: setTimePeriod,
|
||||
onMarketFileLoaded: onMarketFileLoaded,
|
||||
onDailyFileLoaded: onDailyFileLoaded,
|
||||
onSingleFileLoaded: onSingleFileLoaded,
|
||||
onFileSequenceLoaded: onFileSequenceLoaded,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
let LOADING_FILL_STYLE = 'rgba(234, 143, 23, @Opacity)'
|
||||
let LOADED_FILL_STYLE = 'rgba(45, 232, 28, @Opacity)'
|
||||
let UNLOADED_FILL_STYLE = 'rgba(226, 226, 226, @Opacity)'
|
||||
|
||||
let LOADING_STROKE_STYLE = 'rgba(234, 143, 23, @Opacity)'
|
||||
let LOADED_STROKE_STYLE = 'rgba(150, 150, 150, @Opacity)'
|
||||
let UNLOADED_STROKE_STYLE = 'rgba(226, 226, 226, @Opacity)'
|
||||
|
||||
let marketFileProgressBar = {
|
||||
value: 0,
|
||||
animatedValue: 0,
|
||||
fillStyle: UNLOADED_FILL_STYLE,
|
||||
strokeStyle: UNLOADED_STROKE_STYLE,
|
||||
opacity: 0.00
|
||||
}
|
||||
|
||||
let dailyFileProgressBar = {
|
||||
value: 0,
|
||||
animatedValue: 0,
|
||||
fillStyle: UNLOADED_FILL_STYLE,
|
||||
strokeStyle: UNLOADED_STROKE_STYLE,
|
||||
opacity: 0.00
|
||||
}
|
||||
|
||||
let singleFileProgressBar = {
|
||||
value: 0,
|
||||
animatedValue: 0,
|
||||
fillStyle: UNLOADED_FILL_STYLE,
|
||||
strokeStyle: UNLOADED_STROKE_STYLE,
|
||||
opacity: 0.00
|
||||
}
|
||||
|
||||
let fileSequenceProgressBar = {
|
||||
value: 0,
|
||||
animatedValue: 0,
|
||||
fillStyle: UNLOADED_FILL_STYLE,
|
||||
strokeStyle: UNLOADED_STROKE_STYLE,
|
||||
opacity: 0.00
|
||||
}
|
||||
|
||||
let timePeriod = INITIAL_TIME_PERIOD
|
||||
let datetime = NEW_SESSION_INITIAL_DATE
|
||||
|
||||
/* TODO We are in a transition period in which bots and teams images might be located at different places.
|
||||
What we are going to do then is to try to load them from both places and use the variable that finally gets an
|
||||
image. */
|
||||
|
||||
/* This is the legacy image storage. */
|
||||
|
||||
let legacyTeamAvatar
|
||||
let legacyTeamAvatarLoaded = false
|
||||
|
||||
/* TODO Temporary code */
|
||||
let legacyBotAvatar
|
||||
let legacyBotAvatarLoaded = false
|
||||
|
||||
/* Now the plotters images */
|
||||
|
||||
let legacyPlotterBanner
|
||||
let legacyPlotterBannerLoaded = false
|
||||
|
||||
/* We are transitioning towards this */
|
||||
|
||||
let teamAvatar // stores the avatar image of the team the bot portrayed at this card belongs to.
|
||||
let teamAvatarLoaded = false
|
||||
|
||||
/* TODO Temporary code */
|
||||
let botAvatar // stores the avatar image of the team the bot portrayed at this card belongs to.
|
||||
let botAvatarLoaded = false
|
||||
|
||||
/* Add an Event Handler */
|
||||
|
||||
thisObject.eventHandler = newEventHandler()
|
||||
let imagesLoaded = 0
|
||||
|
||||
let lastMouseOver = 0 // This variable is used to animate what happens while we are having a mounse over.
|
||||
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.finalize()
|
||||
thisObject.eventHandler.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.eventHandler = undefined
|
||||
thisObject.status = undefined
|
||||
thisObject.devTeam = undefined
|
||||
thisObject.bot = undefined
|
||||
thisObject.product = undefined
|
||||
thisObject.code = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
|
||||
legacyTeamAvatar = undefined
|
||||
legacyTeamAvatarLoaded = undefined
|
||||
legacyBotAvatar = undefined
|
||||
legacyBotAvatarLoaded = undefined
|
||||
legacyPlotterBanner = undefined
|
||||
timePeriod = undefined
|
||||
datetime = undefined
|
||||
|
||||
LOADING_FILL_STYLE = undefined
|
||||
LOADED_FILL_STYLE = undefined
|
||||
UNLOADED_FILL_STYLE = undefined
|
||||
|
||||
LOADING_STROKE_STYLE = undefined
|
||||
LOADED_STROKE_STYLE = undefined
|
||||
UNLOADED_STROKE_STYLE = undefined
|
||||
|
||||
marketFileProgressBar = undefined
|
||||
dailyFileProgressBar = undefined
|
||||
singleFileProgressBar = undefined
|
||||
fileSequenceProgressBar = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
/* Create this objects continer */
|
||||
try {
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME + thisObject.code)
|
||||
thisObject.container.detectMouseOver = true
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.isClickeable = true
|
||||
|
||||
/* Add information that will later be needed. */
|
||||
|
||||
let team = ecosystem.getTeam(thisObject.product.plotter.devTeam)
|
||||
let plotter
|
||||
if (team !== undefined) {
|
||||
plotter = ecosystem.getPlotter(team, thisObject.product.plotter.codeName)
|
||||
}
|
||||
|
||||
if (plotter !== undefined) {
|
||||
let plotterModule = ecosystem.getPlotterModule(plotter, thisObject.product.plotter.moduleName)
|
||||
|
||||
thisObject.product.plotter.profilePicture = plotterModule.profilePicture
|
||||
thisObject.product.plotter.module = plotterModule
|
||||
}
|
||||
|
||||
/* Lets set the basic dimensions of this thisObject. */
|
||||
|
||||
var position = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.LARGE - 20
|
||||
thisObject.container.frame.height = 100
|
||||
|
||||
/* We retrieve the locally stored status of the Product */
|
||||
|
||||
let storedValue = window.localStorage.getItem(thisObject.code)
|
||||
|
||||
if (storedValue !== null) {
|
||||
thisObject.status = storedValue
|
||||
|
||||
if (thisObject.status === PRODUCT_CARD_STATUS.ON) {
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.LOADING)
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
||||
This happens the first time the app is run on a new browser.
|
||||
|
||||
We will start with all product off, except for the candles chart, since something needs to be shown and allow the user to position themselves
|
||||
on the timeline.
|
||||
|
||||
For the time being, we will hard-code the name of the bot we will turn on by default, since we dont see that change in the near future.
|
||||
|
||||
*/
|
||||
|
||||
const DEFAULT_ON_PRODUCT = 'Poloniex-BTC/USDT-AAMasters-AAOlivia-Candles'
|
||||
|
||||
if (thisObject.code === DEFAULT_ON_PRODUCT) {
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.LOADING)
|
||||
} else {
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.OFF)
|
||||
}
|
||||
}
|
||||
|
||||
/* Lets listen to our own events to react when we have a Mouse Click */
|
||||
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
|
||||
/* WARNING THIS IS TEMPORARY CODE */
|
||||
|
||||
const LEGACY_TEAM = thisObject.devTeam.codeName
|
||||
const REPO = thisObject.bot.repo
|
||||
const PROFILE_PIC = thisObject.bot.profilePicture
|
||||
|
||||
/* The plotter banner, comes from the Legacy Location so far, no matter if the Team is at the Teams Modules or not. */
|
||||
|
||||
const PLOTTER_TEAM = thisObject.product.plotter.devTeam
|
||||
const PLOTTER_REPO = thisObject.product.plotter.codeName
|
||||
const PLOTTER_PROFILE_PIC = thisObject.product.plotter.profilePicture
|
||||
|
||||
legacyPlotterBanner = new Image()
|
||||
legacyPlotterBanner.onload = onLegacyPlotterBanner
|
||||
|
||||
function onLegacyPlotterBanner () {
|
||||
legacyPlotterBannerLoaded = true
|
||||
}
|
||||
|
||||
if (PLOTTER_PROFILE_PIC !== undefined) {
|
||||
legacyPlotterBanner.src = window.canvasApp.urlPrefix + 'Images/' + PLOTTER_TEAM + '/' + PLOTTER_REPO + '/' + PLOTTER_PROFILE_PIC
|
||||
} else {
|
||||
if (thisObject.product.plotter.banner !== undefined) {
|
||||
legacyPlotterBanner.src = window.canvasApp.urlPrefix + 'Images/' + thisObject.product.plotter.banner + '-Banner.PNG'
|
||||
} else {
|
||||
legacyPlotterBanner.src = window.canvasApp.urlPrefix + 'Images/' + 'Default-Banner.PNG'
|
||||
}
|
||||
}
|
||||
|
||||
const TEAM = thisObject.devTeam.codeName.toLowerCase()
|
||||
const BOT = thisObject.bot.codeName.toLowerCase()
|
||||
|
||||
if (window.canvasApp.context.teamProfileImages.get(TEAM) === undefined) {
|
||||
// This means this Team is a Lecay Team, still not at any Module.
|
||||
|
||||
/*
|
||||
Here we will download the images still at the legacy storage.
|
||||
*/
|
||||
|
||||
legacyTeamAvatar = new Image()
|
||||
|
||||
legacyTeamAvatar.onload = onLegacyImageLoad
|
||||
|
||||
function onLegacyImageLoad () {
|
||||
legacyTeamAvatarLoaded = true
|
||||
}
|
||||
|
||||
legacyTeamAvatar.src = window.canvasApp.urlPrefix + 'Images/' + LEGACY_TEAM + '/' + LEGACY_TEAM + '.png'
|
||||
|
||||
legacyBotAvatar = new Image()
|
||||
legacyBotAvatar.onload = onLegacyImageLoadBot
|
||||
|
||||
function onLegacyImageLoadBot () {
|
||||
legacyBotAvatarLoaded = true
|
||||
thisObject.bot.avatar = legacyBotAvatar
|
||||
}
|
||||
|
||||
legacyBotAvatar.src = window.canvasApp.urlPrefix + 'Images/' + LEGACY_TEAM + '/' + REPO + '/' + PROFILE_PIC
|
||||
} else {
|
||||
/*
|
||||
Here we will download the images of teams shareed at the Teams Module.
|
||||
There might be Product Cards of bots beloging to teams not present currently at the Teams Module, in those cases
|
||||
nothing should happen.
|
||||
*/
|
||||
|
||||
teamAvatar = new Image()
|
||||
|
||||
teamAvatar.onload = onImageLoad
|
||||
|
||||
function onImageLoad () {
|
||||
teamAvatarLoaded = true
|
||||
}
|
||||
|
||||
teamAvatar.src = window.canvasApp.context.teamProfileImages.get(TEAM)
|
||||
|
||||
botAvatar = new Image()
|
||||
botAvatar.onload = onImageLoadBot
|
||||
|
||||
function onImageLoadBot () {
|
||||
botAvatarLoaded = true
|
||||
thisObject.bot.avatar = botAvatar
|
||||
}
|
||||
|
||||
botAvatar.src = window.canvasApp.context.fbProfileImages.get(TEAM + '-' + BOT)
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
var container
|
||||
|
||||
/* First we check if this point is inside this space. */
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
} else {
|
||||
/* This point does not belong to this space. */
|
||||
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function setDatetime (pDatetime) {
|
||||
/*
|
||||
|
||||
When the datetime changes from one day to another, this forces cursors to potentially load more files, thus we reset this counter and
|
||||
get ready to receive events on files loaded.
|
||||
|
||||
*/
|
||||
|
||||
let currentDate = Math.trunc(datetime.valueOf() / ONE_DAY_IN_MILISECONDS)
|
||||
let newDate = Math.trunc(pDatetime.valueOf() / ONE_DAY_IN_MILISECONDS)
|
||||
|
||||
datetime = pDatetime
|
||||
|
||||
if (currentDate !== newDate) {
|
||||
if (timePeriod <= _1_HOUR_IN_MILISECONDS) {
|
||||
dailyFileProgressBar.animatedValue = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setTimePeriod (pTimePeriod) {
|
||||
/*
|
||||
|
||||
When the time period below or equal to 1 hour changes, this forces cursors to potentially load more files, thus we reset this counter and
|
||||
get ready to receive events on files loaded.
|
||||
|
||||
*/
|
||||
|
||||
if (timePeriod !== pTimePeriod) {
|
||||
timePeriod = pTimePeriod
|
||||
|
||||
if (timePeriod <= _1_HOUR_IN_MILISECONDS) {
|
||||
dailyFileProgressBar.animatedValue = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMarketFileLoaded (event) {
|
||||
marketFileProgressBar.value = Math.trunc(event.totalValue * 100 / event.totalValue)
|
||||
marketFileProgressBar.fillStyle = LOADING_FILL_STYLE
|
||||
marketFileProgressBar.strokeStyle = LOADING_STROKE_STYLE
|
||||
|
||||
if (marketFileProgressBar.value > 100) { marketFileProgressBar.value = 100 }
|
||||
}
|
||||
|
||||
function onDailyFileLoaded (event) {
|
||||
dailyFileProgressBar.value = Math.trunc(event.currentValue * 100 / event.totalValue)
|
||||
dailyFileProgressBar.fillStyle = LOADING_FILL_STYLE
|
||||
dailyFileProgressBar.strokeStyle = LOADING_STROKE_STYLE
|
||||
|
||||
if (dailyFileProgressBar.value > 100) { dailyFileProgressBar.value = 100 }
|
||||
}
|
||||
|
||||
function onSingleFileLoaded (event) {
|
||||
singleFileProgressBar.value = Math.trunc(event.currentValue * 100 / event.totalValue)
|
||||
singleFileProgressBar.fillStyle = LOADING_FILL_STYLE
|
||||
singleFileProgressBar.strokeStyle = LOADING_STROKE_STYLE
|
||||
|
||||
if (singleFileProgressBar.value > 100) { singleFileProgressBar.value = 100 }
|
||||
}
|
||||
|
||||
function onFileSequenceLoaded (event) {
|
||||
fileSequenceProgressBar.value = Math.trunc(event.currentValue * 100 / event.totalValue)
|
||||
fileSequenceProgressBar.fillStyle = LOADING_FILL_STYLE
|
||||
fileSequenceProgressBar.strokeStyle = LOADING_STROKE_STYLE
|
||||
|
||||
if (fileSequenceProgressBar.value > 100) { fileSequenceProgressBar.value = 100 }
|
||||
}
|
||||
|
||||
function turnOff () {
|
||||
if (thisObject.status !== PRODUCT_CARD_STATUS.OFF) {
|
||||
resetProgressBars()
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.OFF)
|
||||
}
|
||||
}
|
||||
|
||||
function turnOn () {
|
||||
if (thisObject.status === PRODUCT_CARD_STATUS.OFF) {
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.LOADING)
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseClick (event) {
|
||||
switch (thisObject.status) {
|
||||
case PRODUCT_CARD_STATUS.ON:
|
||||
resetProgressBars()
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.OFF)
|
||||
break
|
||||
case PRODUCT_CARD_STATUS.OFF:
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.LOADING)
|
||||
break
|
||||
case PRODUCT_CARD_STATUS.LOADING:
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.OFF)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
function resetProgressBars () {
|
||||
marketFileProgressBar.animatedValue = 0
|
||||
marketFileProgressBar.value = 0
|
||||
marketFileProgressBar.fillStyle = UNLOADED_FILL_STYLE
|
||||
marketFileProgressBar.strokeStyle = UNLOADED_STROKE_STYLE
|
||||
|
||||
dailyFileProgressBar.animatedValue = 0
|
||||
dailyFileProgressBar.value = 0
|
||||
dailyFileProgressBar.fillStyle = UNLOADED_FILL_STYLE
|
||||
dailyFileProgressBar.strokeStyle = UNLOADED_STROKE_STYLE
|
||||
|
||||
singleFileProgressBar.animatedValue = 0
|
||||
singleFileProgressBar.value = 0
|
||||
singleFileProgressBar.fillStyle = UNLOADED_FILL_STYLE
|
||||
singleFileProgressBar.strokeStyle = UNLOADED_STROKE_STYLE
|
||||
|
||||
fileSequenceProgressBar.animatedValue = 0
|
||||
fileSequenceProgressBar.value = 0
|
||||
fileSequenceProgressBar.fillStyle = UNLOADED_FILL_STYLE
|
||||
fileSequenceProgressBar.strokeStyle = UNLOADED_STROKE_STYLE
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
lastMouseOver = 25
|
||||
}
|
||||
|
||||
function changeStatusTo (pNewStatus) {
|
||||
if (thisObject.status !== pNewStatus) {
|
||||
thisObject.status = pNewStatus
|
||||
let eventData = thisObject
|
||||
thisObject.container.eventHandler.raiseEvent('Status Changed', eventData)
|
||||
window.localStorage.setItem(thisObject.code, thisObject.status)
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
drawProductCard()
|
||||
}
|
||||
|
||||
function drawProductCard () {
|
||||
/*
|
||||
Put images on the card.
|
||||
*/
|
||||
|
||||
let fitImagePoint = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
const devTeamImageSize = 20
|
||||
const botImageSize = 20
|
||||
const plotterImageSize = {
|
||||
width: 180,
|
||||
height: 50
|
||||
}
|
||||
|
||||
lastMouseOver-- // Animating the mouse onMouseOver
|
||||
|
||||
if (lastMouseOver > 0) {
|
||||
/* First the Dev Team Profile Picture. */
|
||||
let teamImagePoint = {
|
||||
x: 2,
|
||||
y: thisObject.container.frame.height / 2 - devTeamImageSize / 2
|
||||
}
|
||||
|
||||
teamImagePoint = thisObject.container.frame.frameThisPoint(teamImagePoint)
|
||||
fitImagePoint = thisObject.fitFunction(teamImagePoint)
|
||||
let teamImage
|
||||
if (legacyTeamAvatarLoaded === true) {
|
||||
teamImage = legacyTeamAvatar
|
||||
}
|
||||
if (teamAvatarLoaded === true) {
|
||||
teamImage = teamAvatar
|
||||
}
|
||||
if (teamImage !== undefined && teamImagePoint.y === fitImagePoint.y) {
|
||||
if (teamImage.naturalHeight !== 0) {
|
||||
/* The image is rounded before being displayed. */
|
||||
browserCanvasContext.save()
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(teamImagePoint.x + devTeamImageSize / 2, teamImagePoint.y + devTeamImageSize / 2, devTeamImageSize / 2, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.clip()
|
||||
browserCanvasContext.drawImage(teamImage, teamImagePoint.x, teamImagePoint.y, devTeamImageSize, devTeamImageSize)
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(teamImagePoint.x, teamImagePoint.y, devTeamImageSize / 2, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.clip()
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.restore()
|
||||
}
|
||||
}
|
||||
|
||||
/* Second the Bot's Profile Picture. */
|
||||
if (thisObject.bot.profilePicture !== undefined) {
|
||||
let botImagePoint = {
|
||||
x: thisObject.container.frame.width - botImageSize / 2 - 8,
|
||||
y: thisObject.container.frame.height / 2 - botImageSize / 2
|
||||
}
|
||||
botImagePoint = thisObject.container.frame.frameThisPoint(botImagePoint)
|
||||
fitImagePoint = thisObject.fitFunction(botImagePoint)
|
||||
|
||||
let imageId = thisObject.bot.devTeam + '.' + thisObject.bot.profilePicture
|
||||
/* TODO Temporary code */
|
||||
let botImage
|
||||
botImage = thisObject.bot.avatar
|
||||
if (botImage !== undefined && botImagePoint.y === fitImagePoint.y) {
|
||||
if (botImage.naturalHeight !== 0) {
|
||||
/* The image is rounded before being displayed. */
|
||||
browserCanvasContext.save()
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(botImagePoint.x + botImageSize / 2, botImagePoint.y + botImageSize / 2, botImageSize / 2, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.clip()
|
||||
browserCanvasContext.drawImage(botImage, botImagePoint.x, botImagePoint.y, botImageSize, botImageSize)
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.arc(botImagePoint.x, botImagePoint.y, botImageSize / 2, 0, Math.PI * 2, true)
|
||||
browserCanvasContext.clip()
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.restore()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Third the Plotter's Profile Picture. */
|
||||
if (thisObject.product.plotter.profilePicture !== undefined || thisObject.product.plotter.legacy === false) {
|
||||
let plotterImagePoint = {
|
||||
x: thisObject.container.frame.width / 2 - plotterImageSize.width / 2,
|
||||
y: thisObject.container.frame.height / 2 - plotterImageSize.height / 2
|
||||
}
|
||||
plotterImagePoint = thisObject.container.frame.frameThisPoint(plotterImagePoint)
|
||||
fitImagePoint = {
|
||||
x: 0,
|
||||
y: plotterImagePoint.y + plotterImageSize.height
|
||||
}
|
||||
fitImagePoint = thisObject.fitFunction(fitImagePoint)
|
||||
let imageId = thisObject.product.plotter.devTeam + '.' + thisObject.product.plotter.codeName + '.' + thisObject.product.plotter.moduleName + '.' + thisObject.product.plotter.profilePicture
|
||||
let plotterImage = legacyPlotterBanner
|
||||
if (plotterImage !== undefined && plotterImagePoint.y + plotterImageSize.height === fitImagePoint.y) {
|
||||
if (plotterImage.naturalHeight !== 0) {
|
||||
browserCanvasContext.drawImage(plotterImage, plotterImagePoint.x, plotterImagePoint.y, plotterImageSize.width, plotterImageSize.height)
|
||||
}
|
||||
}
|
||||
}
|
||||
drawProductLoadStatus()
|
||||
|
||||
function drawProductLoadStatus () {
|
||||
let offFillStyle = 'rgba(' + UI_COLOR.RED + ', 0.20)'
|
||||
let onFillStyle = 'rgba(' + UI_COLOR.GREEN + ', 0.20)'
|
||||
let loadingFillStyle = 'rgba(' + UI_COLOR.TITANIUM_YELLOW + ', 0.40)'
|
||||
|
||||
switch (thisObject.status) {
|
||||
case PRODUCT_CARD_STATUS.ON:
|
||||
browserCanvasContext.fillStyle = onFillStyle
|
||||
break
|
||||
case PRODUCT_CARD_STATUS.OFF:
|
||||
browserCanvasContext.fillStyle = offFillStyle
|
||||
break
|
||||
case PRODUCT_CARD_STATUS.LOADING:
|
||||
browserCanvasContext.fillStyle = loadingFillStyle
|
||||
break
|
||||
}
|
||||
|
||||
let centerPoint = {
|
||||
x: thisObject.container.frame.width / 2,
|
||||
y: thisObject.container.frame.height / 2 - 13
|
||||
}
|
||||
|
||||
let point1 = {
|
||||
x: centerPoint.x - plotterImageSize.width / 2,
|
||||
y: centerPoint.y - plotterImageSize.height / 2 - 7
|
||||
}
|
||||
|
||||
let point2 = {
|
||||
x: centerPoint.x + plotterImageSize.width / 2,
|
||||
y: centerPoint.y - plotterImageSize.height / 2 - 7
|
||||
}
|
||||
|
||||
let point3 = {
|
||||
x: centerPoint.x + plotterImageSize.width / 2,
|
||||
y: centerPoint.y - plotterImageSize.height / 2 + 7
|
||||
}
|
||||
|
||||
let point4 = {
|
||||
x: centerPoint.x - plotterImageSize.width / 2,
|
||||
y: centerPoint.y - plotterImageSize.height / 2 + 7
|
||||
}
|
||||
/* Now the transformations. */
|
||||
point1 = thisObject.container.frame.frameThisPoint(point1)
|
||||
point2 = thisObject.container.frame.frameThisPoint(point2)
|
||||
point3 = thisObject.container.frame.frameThisPoint(point3)
|
||||
point4 = thisObject.container.frame.frameThisPoint(point4)
|
||||
|
||||
point1 = thisObject.fitFunction(point1)
|
||||
point2 = thisObject.fitFunction(point2)
|
||||
point3 = thisObject.fitFunction(point3)
|
||||
point4 = thisObject.fitFunction(point4)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
browserCanvasContext.lineTo(point3.x, point3.y)
|
||||
browserCanvasContext.lineTo(point4.x, point4.y)
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.fill()
|
||||
browserCanvasContext.strokeStyle = 'rgba(150, 150, 150, 1)'
|
||||
browserCanvasContext.lineWidth = 0.1
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
/*
|
||||
print the text
|
||||
*/
|
||||
let labelPoint
|
||||
let fontSize = 10
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
let label
|
||||
if (lastMouseOver > 0) {
|
||||
/* devTeam */
|
||||
label = thisObject.devTeam.displayName
|
||||
if (label.length > 10) { label = label.substring(1, 8) + '...' }
|
||||
|
||||
labelPoint = {
|
||||
x: 2 + devTeamImageSize / 2 - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: thisObject.container.frame.height / 2 + devTeamImageSize / 2 + fontSize * FONT_ASPECT_RATIO + 5
|
||||
}
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
||||
labelPoint = thisObject.fitFunction(labelPoint)
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(60, 60, 60, 0.50)'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
/* bot */
|
||||
label = thisObject.bot.displayName
|
||||
if (label.length > 10) { label = label.substring(1, 8) + '...' }
|
||||
|
||||
labelPoint = {
|
||||
x: thisObject.container.frame.width - 8 - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: thisObject.container.frame.height / 2 + devTeamImageSize / 2 + fontSize * FONT_ASPECT_RATIO + 5
|
||||
}
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
||||
labelPoint = thisObject.fitFunction(labelPoint)
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(60, 60, 60, 0.50)'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
/* product */
|
||||
fontSize = 10
|
||||
label = thisObject.product.displayName
|
||||
|
||||
if (thisObject.session !== undefined) {
|
||||
const MAX_LABEL_LENGTH = 20
|
||||
if (thisObject.session.name.length > MAX_LABEL_LENGTH) {
|
||||
label = thisObject.session.name.substring(0, MAX_LABEL_LENGTH) + '...' + ' - ' + label
|
||||
} else {
|
||||
label = thisObject.session.name + ' - ' + label
|
||||
}
|
||||
}
|
||||
labelPoint = {
|
||||
x: 65,
|
||||
y: thisObject.container.frame.height / 2 + 15
|
||||
}
|
||||
labelPoint = {
|
||||
x: thisObject.container.frame.width / 2 - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: thisObject.container.frame.height / 2 - devTeamImageSize / 2 - fontSize * FONT_ASPECT_RATIO - 20
|
||||
}
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
||||
labelPoint = thisObject.fitFunction(labelPoint)
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(60, 60, 60, 1)'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
|
||||
/* ------------------- Progress Bars -------------------------- */
|
||||
|
||||
const ANIMATED_INCREMENT = 5
|
||||
const OPACITY_INCREMENT = 0.05
|
||||
const OPACITY_MIN = 0.1
|
||||
|
||||
let point1
|
||||
let point2
|
||||
let point3
|
||||
let point4
|
||||
|
||||
/* We draw here the Market Progress Bar. */
|
||||
|
||||
/* Animate */
|
||||
|
||||
if (marketFileProgressBar.animatedValue < marketFileProgressBar.value) {
|
||||
marketFileProgressBar.animatedValue = marketFileProgressBar.animatedValue + ANIMATED_INCREMENT
|
||||
marketFileProgressBar.opacity = marketFileProgressBar.opacity + OPACITY_INCREMENT
|
||||
}
|
||||
|
||||
if (marketFileProgressBar.animatedValue >= 100) {
|
||||
marketFileProgressBar.animatedValue = 100
|
||||
|
||||
marketFileProgressBar.opacity = marketFileProgressBar.opacity - OPACITY_INCREMENT
|
||||
if (marketFileProgressBar.opacity < OPACITY_MIN) { marketFileProgressBar.opacity = OPACITY_MIN }
|
||||
|
||||
marketFileProgressBar.fillStyle = LOADED_FILL_STYLE.replace('@Opacity', marketFileProgressBar.opacity.toString())
|
||||
marketFileProgressBar.strokeStyle = LOADED_STROKE_STYLE.replace('@Opacity', marketFileProgressBar.opacity.toString())
|
||||
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.ON)
|
||||
}
|
||||
|
||||
point1 = {
|
||||
x: 0,
|
||||
y: thisObject.container.frame.height - 1
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: thisObject.container.frame.width * marketFileProgressBar.animatedValue / 100,
|
||||
y: thisObject.container.frame.height - 1
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: thisObject.container.frame.width * marketFileProgressBar.animatedValue / 100,
|
||||
y: thisObject.container.frame.height - 3
|
||||
}
|
||||
|
||||
point4 = {
|
||||
x: 0,
|
||||
y: thisObject.container.frame.height - 3
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
|
||||
point1 = thisObject.container.frame.frameThisPoint(point1)
|
||||
point2 = thisObject.container.frame.frameThisPoint(point2)
|
||||
point3 = thisObject.container.frame.frameThisPoint(point3)
|
||||
point4 = thisObject.container.frame.frameThisPoint(point4)
|
||||
|
||||
point1 = thisObject.fitFunction(point1)
|
||||
point2 = thisObject.fitFunction(point2)
|
||||
point3 = thisObject.fitFunction(point3)
|
||||
point4 = thisObject.fitFunction(point4)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
browserCanvasContext.lineTo(point3.x, point3.y)
|
||||
browserCanvasContext.lineTo(point4.x, point4.y)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fillStyle = marketFileProgressBar.fillStyle.replace('@Opacity', marketFileProgressBar.opacity.toString())
|
||||
browserCanvasContext.strokeStyle = marketFileProgressBar.strokeStyle.replace('@Opacity', marketFileProgressBar.opacity.toString())
|
||||
|
||||
browserCanvasContext.fill()
|
||||
browserCanvasContext.lineWidth = 0.1
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
/* We draw here the Daily Progress Bar. */
|
||||
|
||||
/* Animate */
|
||||
|
||||
if (dailyFileProgressBar.animatedValue < dailyFileProgressBar.value) {
|
||||
dailyFileProgressBar.animatedValue = dailyFileProgressBar.animatedValue + ANIMATED_INCREMENT
|
||||
dailyFileProgressBar.opacity = dailyFileProgressBar.opacity + OPACITY_INCREMENT
|
||||
}
|
||||
|
||||
if (dailyFileProgressBar.animatedValue >= 100) {
|
||||
dailyFileProgressBar.animatedValue = 100
|
||||
|
||||
dailyFileProgressBar.opacity = dailyFileProgressBar.opacity - OPACITY_INCREMENT
|
||||
if (dailyFileProgressBar.opacity < OPACITY_MIN) { dailyFileProgressBar.opacity = OPACITY_MIN }
|
||||
|
||||
dailyFileProgressBar.fillStyle = LOADED_FILL_STYLE.replace('@Opacity', dailyFileProgressBar.opacity.toString())
|
||||
dailyFileProgressBar.strokeStyle = LOADED_STROKE_STYLE.replace('@Opacity', dailyFileProgressBar.opacity.toString())
|
||||
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.ON)
|
||||
}
|
||||
|
||||
point1 = {
|
||||
x: 0,
|
||||
y: thisObject.container.frame.height - 4
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: thisObject.container.frame.width * dailyFileProgressBar.animatedValue / 100,
|
||||
y: thisObject.container.frame.height - 4
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: thisObject.container.frame.width * dailyFileProgressBar.animatedValue / 100,
|
||||
y: thisObject.container.frame.height - 6
|
||||
}
|
||||
|
||||
point4 = {
|
||||
x: 0,
|
||||
y: thisObject.container.frame.height - 6
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
|
||||
point1 = thisObject.container.frame.frameThisPoint(point1)
|
||||
point2 = thisObject.container.frame.frameThisPoint(point2)
|
||||
point3 = thisObject.container.frame.frameThisPoint(point3)
|
||||
point4 = thisObject.container.frame.frameThisPoint(point4)
|
||||
|
||||
point1 = thisObject.fitFunction(point1)
|
||||
point2 = thisObject.fitFunction(point2)
|
||||
point3 = thisObject.fitFunction(point3)
|
||||
point4 = thisObject.fitFunction(point4)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
browserCanvasContext.lineTo(point3.x, point3.y)
|
||||
browserCanvasContext.lineTo(point4.x, point4.y)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fillStyle = dailyFileProgressBar.fillStyle.replace('@Opacity', dailyFileProgressBar.opacity.toString())
|
||||
browserCanvasContext.strokeStyle = dailyFileProgressBar.strokeStyle.replace('@Opacity', dailyFileProgressBar.opacity.toString())
|
||||
|
||||
browserCanvasContext.fill()
|
||||
browserCanvasContext.lineWidth = 0.1
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
/* We draw here the Single File Progress Bar. */
|
||||
|
||||
/* Animate */
|
||||
|
||||
if (singleFileProgressBar.animatedValue < singleFileProgressBar.value) {
|
||||
singleFileProgressBar.animatedValue = singleFileProgressBar.animatedValue + ANIMATED_INCREMENT
|
||||
singleFileProgressBar.opacity = singleFileProgressBar.opacity + OPACITY_INCREMENT
|
||||
}
|
||||
|
||||
if (singleFileProgressBar.animatedValue >= 100) {
|
||||
singleFileProgressBar.animatedValue = 100
|
||||
|
||||
singleFileProgressBar.opacity = singleFileProgressBar.opacity - OPACITY_INCREMENT
|
||||
if (singleFileProgressBar.opacity < OPACITY_MIN) { singleFileProgressBar.opacity = OPACITY_MIN }
|
||||
|
||||
singleFileProgressBar.fillStyle = LOADED_FILL_STYLE.replace('@Opacity', singleFileProgressBar.opacity.toString())
|
||||
singleFileProgressBar.strokeStyle = LOADED_STROKE_STYLE.replace('@Opacity', singleFileProgressBar.opacity.toString())
|
||||
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.ON)
|
||||
}
|
||||
|
||||
point1 = {
|
||||
x: 0,
|
||||
y: thisObject.container.frame.height - 7
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: thisObject.container.frame.width * singleFileProgressBar.animatedValue / 100,
|
||||
y: thisObject.container.frame.height - 7
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: thisObject.container.frame.width * singleFileProgressBar.animatedValue / 100,
|
||||
y: thisObject.container.frame.height - 9
|
||||
}
|
||||
|
||||
point4 = {
|
||||
x: 0,
|
||||
y: thisObject.container.frame.height - 9
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
|
||||
point1 = thisObject.container.frame.frameThisPoint(point1)
|
||||
point2 = thisObject.container.frame.frameThisPoint(point2)
|
||||
point3 = thisObject.container.frame.frameThisPoint(point3)
|
||||
point4 = thisObject.container.frame.frameThisPoint(point4)
|
||||
|
||||
point1 = thisObject.fitFunction(point1)
|
||||
point2 = thisObject.fitFunction(point2)
|
||||
point3 = thisObject.fitFunction(point3)
|
||||
point4 = thisObject.fitFunction(point4)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
browserCanvasContext.lineTo(point3.x, point3.y)
|
||||
browserCanvasContext.lineTo(point4.x, point4.y)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fillStyle = singleFileProgressBar.fillStyle.replace('@Opacity', singleFileProgressBar.opacity.toString())
|
||||
browserCanvasContext.strokeStyle = singleFileProgressBar.strokeStyle.replace('@Opacity', singleFileProgressBar.opacity.toString())
|
||||
|
||||
browserCanvasContext.fill()
|
||||
browserCanvasContext.lineWidth = 0.1
|
||||
browserCanvasContext.stroke()
|
||||
|
||||
/* We draw here the File Sequence Progress Bar. */
|
||||
|
||||
/* Animate */
|
||||
|
||||
if (fileSequenceProgressBar.animatedValue < fileSequenceProgressBar.value) {
|
||||
fileSequenceProgressBar.animatedValue = fileSequenceProgressBar.animatedValue + ANIMATED_INCREMENT
|
||||
fileSequenceProgressBar.opacity = fileSequenceProgressBar.opacity + OPACITY_INCREMENT
|
||||
}
|
||||
|
||||
if (fileSequenceProgressBar.animatedValue >= 100) {
|
||||
fileSequenceProgressBar.animatedValue = 100
|
||||
|
||||
fileSequenceProgressBar.opacity = fileSequenceProgressBar.opacity - OPACITY_INCREMENT
|
||||
if (fileSequenceProgressBar.opacity < OPACITY_MIN) { fileSequenceProgressBar.opacity = OPACITY_MIN }
|
||||
|
||||
fileSequenceProgressBar.fillStyle = LOADED_FILL_STYLE.replace('@Opacity', fileSequenceProgressBar.opacity.toString())
|
||||
fileSequenceProgressBar.strokeStyle = LOADED_STROKE_STYLE.replace('@Opacity', fileSequenceProgressBar.opacity.toString())
|
||||
|
||||
changeStatusTo(PRODUCT_CARD_STATUS.ON)
|
||||
}
|
||||
|
||||
point1 = {
|
||||
x: 0,
|
||||
y: thisObject.container.frame.height - 10
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: thisObject.container.frame.width * fileSequenceProgressBar.animatedValue / 100,
|
||||
y: thisObject.container.frame.height - 10
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: thisObject.container.frame.width * fileSequenceProgressBar.animatedValue / 100,
|
||||
y: thisObject.container.frame.height - 11
|
||||
}
|
||||
|
||||
point4 = {
|
||||
x: 0,
|
||||
y: thisObject.container.frame.height - 11
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
|
||||
point1 = thisObject.container.frame.frameThisPoint(point1)
|
||||
point2 = thisObject.container.frame.frameThisPoint(point2)
|
||||
point3 = thisObject.container.frame.frameThisPoint(point3)
|
||||
point4 = thisObject.container.frame.frameThisPoint(point4)
|
||||
|
||||
point1 = thisObject.fitFunction(point1)
|
||||
point2 = thisObject.fitFunction(point2)
|
||||
point3 = thisObject.fitFunction(point3)
|
||||
point4 = thisObject.fitFunction(point4)
|
||||
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y)
|
||||
browserCanvasContext.lineTo(point3.x, point3.y)
|
||||
browserCanvasContext.lineTo(point4.x, point4.y)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.fillStyle = fileSequenceProgressBar.fillStyle.replace('@Opacity', fileSequenceProgressBar.opacity.toString())
|
||||
browserCanvasContext.strokeStyle = fileSequenceProgressBar.strokeStyle.replace('@Opacity', fileSequenceProgressBar.opacity.toString())
|
||||
|
||||
browserCanvasContext.fill()
|
||||
browserCanvasContext.lineWidth = 0.1
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,506 +0,0 @@
|
||||
function newProductsPanel () {
|
||||
let thisObject = {
|
||||
name: 'Products Panel',
|
||||
fitFunction: undefined,
|
||||
container: undefined,
|
||||
productCards: [],
|
||||
getLoadingProductCards: getLoadingProductCards,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize
|
||||
}
|
||||
|
||||
/* Cointainer stuff */
|
||||
|
||||
let container = newContainer()
|
||||
|
||||
container.initialize()
|
||||
|
||||
container.isDraggeable = true
|
||||
container.isWheelable = true
|
||||
|
||||
thisObject.container = container
|
||||
|
||||
let isInitialized = false
|
||||
|
||||
let cardsMap = new Map()
|
||||
let visibleProductCards = []
|
||||
let firstVisibleCard = 1
|
||||
|
||||
/* Needed Variables */
|
||||
|
||||
const CANRD_SEPARATION = 5
|
||||
let panelTabButton
|
||||
|
||||
let exchange
|
||||
let market
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize (pExchange, pMarket) {
|
||||
exchange = pExchange
|
||||
market = pMarket
|
||||
|
||||
thisObject.container.name = 'Layers @ ' + exchange + ' ' + market.assetB + '/' + market.assetA
|
||||
thisObject.container.frame.containerName = thisObject.container.name
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.LARGE
|
||||
thisObject.container.frame.height = UI_PANEL.HEIGHT.LARGE * 1.5 // viewPort.visibleArea.bottomLeft.y - viewPort.visibleArea.topLeft.y // UI_PANEL.HEIGHT.LARGE;
|
||||
|
||||
let position = {
|
||||
x: viewPort.visibleArea.topLeft.x,
|
||||
y: viewPort.visibleArea.topLeft.y// viewPort.visibleArea.bottomLeft.y - thisObject.container.frame.height
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
panelTabButton.fitFunction = thisObject.fitFunction
|
||||
panelTabButton.initialize()
|
||||
|
||||
/* First thing is to build the thisObject.productCards array */
|
||||
let ecosystem = JSON.parse(window.localStorage.getItem('ecosystem'))
|
||||
if (ecosystem === null || ecosystem === undefined) {
|
||||
ecosystem = getUserEcosystem()
|
||||
}
|
||||
|
||||
/* For legacy plotters, we will add product cards based on the old ecosystem file */
|
||||
for (let i = 0; i < ecosystem.devTeams.length; i++) {
|
||||
let devTeam = ecosystem.devTeams[i]
|
||||
|
||||
for (let j = 0; j < devTeam.bots.length; j++) {
|
||||
let bot = devTeam.bots[j]
|
||||
if (bot.type !== 'Indicator Bot Instance') { continue }
|
||||
|
||||
if (bot.products !== undefined) {
|
||||
for (let k = 0; k < bot.products.length; k++) {
|
||||
let product = bot.products[k]
|
||||
|
||||
addProductCard(devTeam, bot, product)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For new plotters defined at the UI, we will add product cards based on what we find at the workspace */
|
||||
let workspaceNode = canvas.designerSpace.workspace.workspaceNode
|
||||
for (let i = 0; i < workspaceNode.rootNodes.length; i++) {
|
||||
let rootNode = workspaceNode.rootNodes[i]
|
||||
if (rootNode.type === 'Team') {
|
||||
let teamNode = rootNode
|
||||
|
||||
let team = {}
|
||||
if (teamNode.code === undefined) { continue }
|
||||
try {
|
||||
let code = JSON.parse(teamNode.code)
|
||||
team.codeName = code.codeName
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
for (let j = 0; j < teamNode.indicatorBots.length; j++) {
|
||||
let botNode = teamNode.indicatorBots[j]
|
||||
|
||||
let bot = {}
|
||||
if (botNode.code === undefined) { continue }
|
||||
try {
|
||||
let code = JSON.parse(botNode.code)
|
||||
bot.codeName = code.codeName
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (let k = 0; k < botNode.products.length; k++) {
|
||||
let productNode = botNode.products[k]
|
||||
|
||||
let product = {}
|
||||
if (productNode.code === undefined) { continue }
|
||||
try {
|
||||
let code = JSON.parse(productNode.code)
|
||||
product.codeName = code.codeName
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (productNode.payload.referenceParent === undefined) { continue }
|
||||
let plotterModuleNode = productNode.payload.referenceParent
|
||||
|
||||
let plotterModule = {}
|
||||
if (plotterModuleNode.code === undefined) { continue }
|
||||
try {
|
||||
let code = JSON.parse(plotterModuleNode.code)
|
||||
plotterModule.codeName = code.codeName
|
||||
plotterModule.banner = code.banner
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (plotterModuleNode.payload.parentNode === undefined) { continue }
|
||||
let plotterNode = plotterModuleNode.payload.parentNode
|
||||
|
||||
let plotter = {}
|
||||
if (plotterNode.code === undefined) { continue }
|
||||
try {
|
||||
let code = JSON.parse(plotterNode.code)
|
||||
plotter.codeName = code.codeName
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (plotterNode.payload.parentNode === undefined) { continue }
|
||||
let plotterTeamNode = plotterNode.payload.parentNode
|
||||
|
||||
let plotterTeam = {}
|
||||
if (plotterTeamNode.code === undefined) { continue }
|
||||
try {
|
||||
let code = JSON.parse(plotterTeamNode.code)
|
||||
plotterTeam.codeName = code.codeName
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
|
||||
/* Conversion to fit old format */
|
||||
product.plotter = plotter
|
||||
product.plotter.devTeam = plotterTeam.codeName
|
||||
product.plotter.moduleName = plotterModule.codeName
|
||||
product.plotter.banner = plotterModule.banner
|
||||
product.plotter.legacy = false
|
||||
product.plotter.module = { panels: [] }
|
||||
product.displayName = productNode.name
|
||||
product.dataSets = []
|
||||
product.exchangeList = [{'name': 'Poloniex'}]
|
||||
product.node = productNode
|
||||
team.displayName = teamNode.name
|
||||
team.host = {'url': 'localhost'}
|
||||
bot.displayName = botNode.name
|
||||
|
||||
for (let m = 0; m < productNode.datasets.length; m++) {
|
||||
let dataset = productNode.datasets[m]
|
||||
|
||||
if (dataset.code === undefined) { continue }
|
||||
try {
|
||||
let code = JSON.parse(dataset.code)
|
||||
product.dataSets.push(code)
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
addProductCard(team, bot, product)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
isInitialized = true
|
||||
}
|
||||
|
||||
function removeProductCard (code) {
|
||||
let productCard = cardsMap.get(code)
|
||||
cardsMap.delete(code)
|
||||
productCard.turnOff()
|
||||
productCard.finalize()
|
||||
}
|
||||
|
||||
function addProductCard (devTeam, bot, product, session) {
|
||||
/* Now we create Product objects */
|
||||
let productCard = newProductCard()
|
||||
|
||||
productCard.devTeam = devTeam
|
||||
productCard.bot = bot
|
||||
productCard.product = product
|
||||
productCard.fitFunction = thisObject.fitFunction
|
||||
productCard.code = exchange + '-' + market.assetB + '/' + market.assetA + '-' + devTeam.codeName + '-' + bot.codeName + '-' + product.codeName
|
||||
|
||||
if (session !== undefined) {
|
||||
productCard.code = productCard.code + '-' + session.id
|
||||
}
|
||||
productCard.session = session
|
||||
|
||||
/* Initialize it */
|
||||
productCard.initialize()
|
||||
cardsMap.set(productCard.code, productCard)
|
||||
|
||||
/* Container Stuff */
|
||||
productCard.container.displacement.parentDisplacement = thisObject.container.displacement
|
||||
productCard.container.frame.parentFrame = thisObject.container.frame
|
||||
productCard.container.parentContainer = thisObject.container
|
||||
productCard.container.isWheelable = true
|
||||
|
||||
/* Positioning within thisObject Panel */
|
||||
let position = {
|
||||
x: 10,
|
||||
y: thisObject.container.frame.height - thisObject.container.frame.getBodyHeight()
|
||||
}
|
||||
|
||||
productCard.container.frame.position.x = position.x
|
||||
productCard.container.frame.position.y = position.y + productCard.container.frame.height * thisObject.productCards.length + CANRD_SEPARATION
|
||||
|
||||
/* Add to the Product Array */
|
||||
thisObject.productCards.push(productCard)
|
||||
|
||||
/* Add to Visible Product Array */
|
||||
if (productCard.container.frame.position.y + productCard.container.frame.height < thisObject.container.frame.height) {
|
||||
visibleProductCards.push(productCard)
|
||||
}
|
||||
|
||||
/* Listen to Status Changes Events */
|
||||
productCard.container.eventHandler.listenToEvent('Status Changed', onProductCardStatusChanged)
|
||||
productCard.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
|
||||
return productCard
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
delta = event.wheelDelta
|
||||
if (delta > 0) {
|
||||
delta = -1
|
||||
} else {
|
||||
delta = 1
|
||||
}
|
||||
|
||||
firstVisibleCard = firstVisibleCard + delta
|
||||
|
||||
calculateVisbleProductCards()
|
||||
}
|
||||
|
||||
function calculateVisbleProductCards () {
|
||||
let availableSlots = visibleProductCards.length
|
||||
|
||||
if (firstVisibleCard < 1) { firstVisibleCard = 1 }
|
||||
if (firstVisibleCard > (thisObject.productCards.length - availableSlots + 1)) { firstVisibleCard = thisObject.productCards.length - availableSlots + 1 }
|
||||
|
||||
visibleProductCards = []
|
||||
|
||||
for (let i = 0; i < thisObject.productCards.length; i++) {
|
||||
if (i + 1 >= firstVisibleCard && i + 1 < firstVisibleCard + availableSlots) {
|
||||
let productCard = thisObject.productCards[i]
|
||||
|
||||
/* Positioning within thisObject Panel */
|
||||
|
||||
let position = {
|
||||
x: 10,
|
||||
y: thisObject.container.frame.height - thisObject.container.frame.getBodyHeight()
|
||||
}
|
||||
productCard.container.frame.position.x = position.x
|
||||
productCard.container.frame.position.y = position.y + productCard.container.frame.height * visibleProductCards.length + CANRD_SEPARATION
|
||||
|
||||
/* Add to Visible Product Array */
|
||||
|
||||
visibleProductCards.push(productCard)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onProductCardStatusChanged (pProductCard) {
|
||||
thisObject.container.eventHandler.raiseEvent('Product Card Status Changed', pProductCard)
|
||||
}
|
||||
|
||||
function getLoadingProductCards () {
|
||||
/* Returns all thisObject.productCards which status is LOADING */
|
||||
|
||||
let onProducts = []
|
||||
|
||||
for (let i = 0; i < thisObject.productCards.length; i++) {
|
||||
if (thisObject.productCards[i].status === PRODUCT_CARD_STATUS.LOADING) {
|
||||
onProducts.push(thisObject.productCards[i])
|
||||
}
|
||||
}
|
||||
|
||||
return onProducts
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
let container
|
||||
|
||||
container = panelTabButton.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 < visibleProductCards.length; i++) {
|
||||
container = visibleProductCards[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) {
|
||||
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 physics () {
|
||||
if (isInitialized === false) { return }
|
||||
|
||||
/*
|
||||
The overall idea here is that we need to keep syncronized the panel with the layers that are
|
||||
defined at the Designer. Users can connect or disconnect any objext resulting in changes in which
|
||||
are valid layers and which not at any point in time. So what we do here is trying to keep the panel
|
||||
only with the layers that are connected to each Definition structure.
|
||||
|
||||
To achieve this, first we are going to move all session related cards to a local array. Then we are
|
||||
going to check for layers at the designer, and will move back the cards which still have layers well
|
||||
defined to where they were.
|
||||
|
||||
If we find new layers we will add them at that point. Finally, the cards that still remain at the
|
||||
local array after all the layers at the designer have been processed, are turned off and discarded.
|
||||
*/
|
||||
|
||||
let localProductCards = []
|
||||
moveToLocalProductCards()
|
||||
synchronizeLayersAndProductCards()
|
||||
|
||||
/* At this poins all the cards still at the local array need to be removed from the panel. */
|
||||
turnOffUnusedProducCards()
|
||||
calculateVisbleProductCards()
|
||||
|
||||
function synchronizeLayersAndProductCards () {
|
||||
/* We will look into the ecosystem to know which Trading bots are defined there. */
|
||||
let ecosystem = JSON.parse(window.localStorage.getItem('ecosystem'))
|
||||
if (ecosystem === null || ecosystem === undefined) {
|
||||
ecosystem = getUserEcosystem()
|
||||
}
|
||||
|
||||
/* Then we get an Array of all instances of this bot placed at Definitions on the Workspace. */
|
||||
let tradingBotInstances = canvas.designerSpace.workspace.getAllTradingBotInstances()
|
||||
|
||||
/* Here we will go through all the instances of trading engines and see their layers, to see
|
||||
if we can find a matching layer. */
|
||||
|
||||
for (let n = 0; n < tradingBotInstances.length; n++) {
|
||||
let tradingBotInstance = tradingBotInstances[n]
|
||||
let code
|
||||
let instanceBot
|
||||
let instanceTeam
|
||||
|
||||
for (let m = 0; m < tradingBotInstance.processes.length; m++) {
|
||||
let process = tradingBotInstance.processes[m]
|
||||
try {
|
||||
code = JSON.parse(process.payload.referenceParent.payload.parentNode.code)
|
||||
instanceBot = code.codeName
|
||||
code = JSON.parse(process.payload.referenceParent.payload.parentNode.payload.parentNode.code)
|
||||
instanceTeam = code.codeName
|
||||
} catch (err) {
|
||||
continue
|
||||
}
|
||||
for (let i = 0; i < ecosystem.devTeams.length; i++) {
|
||||
let devTeam = ecosystem.devTeams[i]
|
||||
|
||||
for (let j = 0; j < devTeam.bots.length; j++) {
|
||||
let bot = devTeam.bots[j]
|
||||
if (bot.type !== 'Trading Bot Instance') { continue }
|
||||
|
||||
if (devTeam.codeName === instanceTeam && bot.codeName === instanceBot) {
|
||||
/* We found an instance of the same Trading we are currently looking at.
|
||||
Next thing to do is to see its layers to see if we can match it with the current product. */
|
||||
|
||||
if (process.session !== undefined) {
|
||||
if (process.session.layerManager !== undefined) {
|
||||
let layerManager = process.session.layerManager
|
||||
if (layerManager.payload.floatingObject.isCollapsed !== true) {
|
||||
if (bot.products !== undefined) {
|
||||
for (let k = 0; k < bot.products.length; k++) {
|
||||
let product = bot.products[k]
|
||||
|
||||
for (let p = 0; p < layerManager.layers.length; p++) {
|
||||
let layer = layerManager.layers[p]
|
||||
let layerCode
|
||||
try {
|
||||
layerCode = JSON.parse(layer.code)
|
||||
} catch (err) {
|
||||
// if we can not parse this, then we ignore this trading engine.
|
||||
}
|
||||
|
||||
if (product.codeName === layerCode.product) {
|
||||
/* We have a layer that is matching the current product */
|
||||
let cardCode = exchange + '-' + market.assetB + '/' + market.assetA + '-' + devTeam.codeName + '-' + bot.codeName + '-' + product.codeName + '-' + process.session.id
|
||||
let cardFound = removeFromLocalProductCards(cardCode)
|
||||
if (cardFound !== true) {
|
||||
productCard = addProductCard(devTeam, bot, product, process.session)
|
||||
onProductCardStatusChanged(productCard)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function moveToLocalProductCards () {
|
||||
removeNext()
|
||||
|
||||
function removeNext () {
|
||||
for (let i = 0; i < thisObject.productCards.length; i++) {
|
||||
let productCard = thisObject.productCards[i]
|
||||
if (productCard.session !== undefined) {
|
||||
thisObject.productCards.splice(i, 1)
|
||||
localProductCards.push(productCard)
|
||||
removeNext()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeFromLocalProductCards (code) {
|
||||
for (let i = 0; i < localProductCards.length; i++) {
|
||||
let productCard = localProductCards[i]
|
||||
if (productCard.code === code) {
|
||||
thisObject.productCards.push(productCard)
|
||||
localProductCards.splice(i, 1)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function turnOffUnusedProducCards () {
|
||||
for (let i = 0; i < localProductCards.length; i++) {
|
||||
let productCard = localProductCards[i]
|
||||
removeProductCard(productCard.code)
|
||||
}
|
||||
}
|
||||
}
|
||||
function draw () {
|
||||
if (isInitialized === false) { return }
|
||||
|
||||
thisObject.container.frame.draw(false, false, true, thisObject.fitFunction)
|
||||
|
||||
for (let i = 0; i < visibleProductCards.length; i++) {
|
||||
visibleProductCards[i].draw()
|
||||
}
|
||||
|
||||
panelTabButton.draw()
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
|
||||
function newTimeControlPanel () {
|
||||
let thisObject = {
|
||||
container: undefined,
|
||||
setDatetime: setDatetime,
|
||||
datetimeDisplay: undefined,
|
||||
stepDisplay: undefined,
|
||||
draw: draw,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize
|
||||
}
|
||||
|
||||
let container = newContainer()
|
||||
container.initialize()
|
||||
container.isDraggeable = true
|
||||
thisObject.container = container
|
||||
thisObject.container.frame.containerName = 'Current Datetime'
|
||||
|
||||
let timePeriod
|
||||
let panelTabButton
|
||||
|
||||
return thisObject
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.SMALL
|
||||
thisObject.container.frame.height = UI_PANEL.HEIGHT.SMALL
|
||||
|
||||
let position = {
|
||||
x: (viewPort.visibleArea.topRight.x - viewPort.visibleArea.topLeft.x) / 2 - thisObject.container.frame.width / 2,
|
||||
y: viewPort.visibleArea.bottomLeft.y - thisObject.container.frame.height
|
||||
}
|
||||
|
||||
thisObject.container.frame.position = position
|
||||
|
||||
panelTabButton = newPanelTabButton()
|
||||
panelTabButton.parentContainer = thisObject.container
|
||||
panelTabButton.container.frame.parentFrame = thisObject.container.frame
|
||||
panelTabButton.initialize()
|
||||
|
||||
let datetime = NEW_SESSION_INITIAL_DATE
|
||||
|
||||
let datetimeDisplay = {
|
||||
currentDatetime: datetime,
|
||||
addTime: addTime,
|
||||
draw: drawTimeDisplay
|
||||
}
|
||||
|
||||
thisObject.datetimeDisplay = datetimeDisplay
|
||||
|
||||
viewPort.eventHandler.listenToEvent('Zoom Changed', onZoomChanged)
|
||||
timePeriod = INITIAL_TIME_PERIOD
|
||||
}
|
||||
|
||||
function onBotChangedTime (pNewDatetime) {
|
||||
let newDatetime = new Date(pNewDatetime)
|
||||
|
||||
thisObject.container.eventHandler.raiseEvent('Datetime Changed', newDatetime)
|
||||
}
|
||||
|
||||
function onZoomChanged (event) {
|
||||
if (event !== undefined) { // it is undefined when the level is just being animated.
|
||||
timePeriod = recalculatePeriod(event.newLevel)
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
let container
|
||||
|
||||
container = panelTabButton.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) {
|
||||
/* The point does not belong to any inner container, so we return the current container. */
|
||||
|
||||
return thisObject.container
|
||||
} else {
|
||||
/* This point does not belong to thisObject space. */
|
||||
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function setDatetime (pDatetime) {
|
||||
thisObject.datetimeDisplay.currentDatetime = new Date(pDatetime)
|
||||
}
|
||||
|
||||
function addTime (seconds) {
|
||||
let newDate = thisObject.datetimeDisplay.currentDatetime
|
||||
|
||||
newDate.setSeconds(newDate.getSeconds() + seconds)
|
||||
thisObject.datetimeDisplay.currentDatetime = newDate
|
||||
}
|
||||
|
||||
function draw () {
|
||||
return
|
||||
thisObject.container.frame.draw(false, false, true)
|
||||
thisObject.datetimeDisplay.draw()
|
||||
panelTabButton.draw()
|
||||
}
|
||||
|
||||
function drawTimeDisplay () {
|
||||
let fontSize = 10
|
||||
|
||||
let label = thisObject.datetimeDisplay.currentDatetime.toUTCString()
|
||||
let labelArray = label.split(' ')
|
||||
|
||||
label = labelArray[0] + ' ' + labelArray[1] + ' ' + labelArray[2] + ' ' + labelArray[3]
|
||||
|
||||
/* Now we transform x on the actual coordinate on the canvas. */
|
||||
|
||||
let labelPoint = {
|
||||
x: thisObject.container.frame.width / 2 - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: thisObject.container.frame.height * 4.4 / 10
|
||||
}
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(60, 60, 60, 0.50)'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
|
||||
/* The time */
|
||||
|
||||
label = labelArray[4] + ' ' + labelArray[5]
|
||||
|
||||
/* Now we transform x on the actual coordinate on the canvas. */
|
||||
|
||||
labelPoint = {
|
||||
x: thisObject.container.frame.width / 2 - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: thisObject.container.frame.height * 6.5 / 10
|
||||
}
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(60, 60, 60, 0.50)'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
|
||||
if (timePeriod > _45_MINUTES_IN_MILISECONDS) {
|
||||
label = timePeriod / _1_HOUR_IN_MILISECONDS + ' hs'
|
||||
} else {
|
||||
label = timePeriod / _1_MINUTE_IN_MILISECONDS + ' min'
|
||||
}
|
||||
|
||||
/* Now we transform x on the actual coordinate on the canvas. */
|
||||
|
||||
labelPoint = {
|
||||
x: thisObject.container.frame.width / 2 - label.length / 2 * fontSize * FONT_ASPECT_RATIO,
|
||||
y: thisObject.container.frame.height * 8.5 / 10
|
||||
}
|
||||
|
||||
labelPoint = thisObject.container.frame.frameThisPoint(labelPoint)
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(60, 60, 60, 0.50)'
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
}
|
||||
+116
-106
@@ -6,40 +6,30 @@ function newPlotter () {
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let thisObject = {
|
||||
|
||||
/* Events declared outside the plotter. */
|
||||
|
||||
currentRecord: undefined,
|
||||
container: undefined,
|
||||
onDailyFileLoaded: onDailyFileLoaded,
|
||||
|
||||
// Main functions and properties.
|
||||
|
||||
initialize: initialize,
|
||||
finalize: finalize,
|
||||
container: undefined,
|
||||
getContainer: getContainer,
|
||||
setTimePeriod: setTimePeriod,
|
||||
setTimeFrame: setTimeFrame,
|
||||
setDatetime: setDatetime,
|
||||
recalculateScale: recalculateScale,
|
||||
draw: draw,
|
||||
|
||||
// Secondary functions and properties.
|
||||
|
||||
currentRecord: undefined // ---> Check Here
|
||||
setCoordinateSystem: setCoordinateSystem,
|
||||
draw: draw
|
||||
}
|
||||
|
||||
let container = newContainer()
|
||||
container.initialize()
|
||||
thisObject.container = container
|
||||
|
||||
let timeLineCoordinateSystem = newTimeLineCoordinateSystem() // Needed to be able to plot on the timeline.
|
||||
let slotCoordinateSystem // Needed to be able to plot on a slot over the timeline.
|
||||
let coordinateSystem
|
||||
let plotterModuleConfig
|
||||
let slotHeight = (viewPort.visibleArea.bottomRight.y - viewPort.visibleArea.topLeft.y) / 10 // This is the amount of slots available
|
||||
let slotHeight = (canvas.chartSpace.viewport.visibleArea.bottomRight.y - canvas.chartSpace.viewport.visibleArea.topLeft.y) / 10 // This is the amount of slots available
|
||||
let mustRecalculateDataPoints = false
|
||||
let atMousePositionFillStyles = new Map()
|
||||
let atMousePositionStrokeStyles = new Map()
|
||||
|
||||
let timePeriod // This will hold the current Time Period the user is at.
|
||||
let timeFrame // This will hold the current Time Frame the user is at.
|
||||
let datetime // This will hold the current Datetime the user is at.
|
||||
|
||||
let marketFile // This is the current Market File being plotted.
|
||||
@@ -51,13 +41,17 @@ function newPlotter () {
|
||||
let productDefinition // Here we store a snapshot of the product definition which references this plotter.
|
||||
|
||||
let records = [] // We will have the information to be plotted here.
|
||||
let userPositionDate
|
||||
|
||||
let onMouseOverEventSuscriptionId
|
||||
let zoomChangedEventSubscriptionId
|
||||
let offsetChangedEventSubscriptionId
|
||||
let dragFinishedEventSubscriptionId
|
||||
let dimmensionsChangedEventSubscriptionId
|
||||
let marketFilesUpdatedEventSubscriptionId
|
||||
let dailyFilesUpdatedEventSubscriptionId
|
||||
let onDisplaceEventSubscriptionId
|
||||
let scaleChangedEventSubscriptionId
|
||||
|
||||
let logged = false
|
||||
return thisObject
|
||||
@@ -65,25 +59,27 @@ function newPlotter () {
|
||||
function finalize () {
|
||||
try {
|
||||
/* Stop listening to the necesary events. */
|
||||
viewPort.eventHandler.stopListening(zoomChangedEventSubscriptionId)
|
||||
viewPort.eventHandler.stopListening(offsetChangedEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
|
||||
canvas.chartSpace.viewport.eventHandler.stopListening(zoomChangedEventSubscriptionId)
|
||||
canvas.chartSpace.viewport.eventHandler.stopListening(offsetChangedEventSubscriptionId)
|
||||
canvas.eventHandler.stopListening(dragFinishedEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(dimmensionsChangedEventSubscriptionId)
|
||||
marketFiles.eventHandler.stopListening(marketFilesUpdatedEventSubscriptionId)
|
||||
dailyFiles.eventHandler.stopListening(dailyFilesUpdatedEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onDisplaceEventSubscriptionId)
|
||||
|
||||
/* Clear References */
|
||||
marketFiles = undefined
|
||||
dailyFiles = undefined
|
||||
|
||||
datetime = undefined
|
||||
timePeriod = undefined
|
||||
timeFrame = undefined
|
||||
|
||||
marketFile = undefined
|
||||
fileCursor = undefined
|
||||
|
||||
timeLineCoordinateSystem = undefined
|
||||
slotCoordinateSystem = undefined
|
||||
finalizeCoordinateSystem()
|
||||
coordinateSystem = undefined
|
||||
plotterModuleConfig = undefined
|
||||
slotHeight = undefined
|
||||
mustRecalculateDataPoints = undefined
|
||||
@@ -94,37 +90,38 @@ function newPlotter () {
|
||||
}
|
||||
}
|
||||
|
||||
function initialize (pStorage, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction, pProductDefinition) {
|
||||
function initialize (pStorage, pDatetime, pTimeFrame, pCoordinateSystem, callBackFunction, pProductDefinition) {
|
||||
try {
|
||||
/* Store the information received. */
|
||||
marketFiles = pStorage.marketFiles[0]
|
||||
dailyFiles = pStorage.dailyFiles[0]
|
||||
|
||||
datetime = pDatetime
|
||||
timePeriod = pTimePeriod
|
||||
timeFrame = pTimeFrame
|
||||
coordinateSystem = pCoordinateSystem
|
||||
initializeCoordinateSystem()
|
||||
|
||||
productDefinition = pProductDefinition
|
||||
|
||||
/* We need a Market File in order to calculate the Y scale, since this scale depends on actual data. */
|
||||
marketFile = marketFiles.getFile(ONE_DAY_IN_MILISECONDS) // This file is the one processed faster.
|
||||
|
||||
recalculateScale()
|
||||
|
||||
/* Now we set the right files according to current Period. */
|
||||
marketFile = marketFiles.getFile(pTimePeriod)
|
||||
fileCursor = dailyFiles.getFileCursor(pTimePeriod)
|
||||
marketFile = marketFiles.getFile(pTimeFrame)
|
||||
fileCursor = dailyFiles.getFileCursor(pTimeFrame)
|
||||
|
||||
/* Listen to the necesary events. */
|
||||
zoomChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent('Zoom Changed', onZoomChanged)
|
||||
offsetChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent('Offset Changed', onOffsetChanged)
|
||||
zoomChangedEventSubscriptionId = canvas.chartSpace.viewport.eventHandler.listenToEvent('Zoom Changed', onViewportZoomChanged)
|
||||
offsetChangedEventSubscriptionId = canvas.chartSpace.viewport.eventHandler.listenToEvent('Position Changed', onViewportPositionChanged)
|
||||
dragFinishedEventSubscriptionId = canvas.eventHandler.listenToEvent('Drag Finished', onDragFinished)
|
||||
marketFilesUpdatedEventSubscriptionId = marketFiles.eventHandler.listenToEvent('Files Updated', onMarketFilesUpdated)
|
||||
dailyFilesUpdatedEventSubscriptionId = dailyFiles.eventHandler.listenToEvent('Files Updated', onDailyFilesUpdated)
|
||||
onDisplaceEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onDisplace', onDisplace)
|
||||
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
|
||||
/* Get ready for plotting. */
|
||||
recalculate()
|
||||
dimmensionsChangedEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('Dimmensions Changed', function () {
|
||||
recalculateScale()
|
||||
recalculate()
|
||||
})
|
||||
|
||||
@@ -135,9 +132,27 @@ function newPlotter () {
|
||||
}
|
||||
}
|
||||
|
||||
function initializeCoordinateSystem () {
|
||||
scaleChangedEventSubscriptionId = coordinateSystem.eventHandler.listenToEvent('Scale Changed', onScaleChanged)
|
||||
}
|
||||
|
||||
function finalizeCoordinateSystem () {
|
||||
coordinateSystem.eventHandler.stopListening(scaleChangedEventSubscriptionId)
|
||||
}
|
||||
|
||||
function onScaleChanged () {
|
||||
mustRecalculateDataPoints = true
|
||||
recalculate()
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
let userPosition = getDateFromPoint(event, thisObject.container, coordinateSystem)
|
||||
userPositionDate = userPosition.valueOf()
|
||||
}
|
||||
|
||||
function onMarketFilesUpdated () {
|
||||
try {
|
||||
let newMarketFile = marketFiles.getFile(timePeriod)
|
||||
let newMarketFile = marketFiles.getFile(timeFrame)
|
||||
if (newMarketFile !== undefined) {
|
||||
marketFile = newMarketFile
|
||||
mustRecalculateDataPoints = true
|
||||
@@ -150,7 +165,7 @@ function newPlotter () {
|
||||
|
||||
function onDailyFilesUpdated () {
|
||||
try {
|
||||
let newFileCursor = dailyFiles.getFileCursor(timePeriod)
|
||||
let newFileCursor = dailyFiles.getFileCursor(timeFrame)
|
||||
if (newFileCursor !== undefined) {
|
||||
fileCursor = newFileCursor
|
||||
mustRecalculateDataPoints = true
|
||||
@@ -165,8 +180,8 @@ function newPlotter () {
|
||||
try {
|
||||
let container
|
||||
/* First we check if this point is inside this space. */
|
||||
if (this.container.frame.isThisPointHere(point) === true) {
|
||||
return this.container
|
||||
if (thisObject.container.frame.isThisPointHere(point) === true) {
|
||||
return thisObject.container
|
||||
} else {
|
||||
/* This point does not belong to this space. */
|
||||
return undefined
|
||||
@@ -176,20 +191,20 @@ function newPlotter () {
|
||||
}
|
||||
}
|
||||
|
||||
function setTimePeriod (pTimePeriod) {
|
||||
function setTimeFrame (pTimeFrame) {
|
||||
try {
|
||||
if (timePeriod !== pTimePeriod) {
|
||||
timePeriod = pTimePeriod
|
||||
if (timeFrame !== pTimeFrame) {
|
||||
timeFrame = pTimeFrame
|
||||
mustRecalculateDataPoints = true
|
||||
if (timePeriod >= _1_HOUR_IN_MILISECONDS) {
|
||||
let newMarketFile = marketFiles.getFile(pTimePeriod)
|
||||
if (timeFrame >= _1_HOUR_IN_MILISECONDS) {
|
||||
let newMarketFile = marketFiles.getFile(pTimeFrame)
|
||||
|
||||
if (newMarketFile !== undefined) {
|
||||
marketFile = newMarketFile
|
||||
recalculate()
|
||||
}
|
||||
} else {
|
||||
let newFileCursor = dailyFiles.getFileCursor(pTimePeriod)
|
||||
let newFileCursor = dailyFiles.getFileCursor(pTimeFrame)
|
||||
|
||||
if (newFileCursor !== undefined) {
|
||||
fileCursor = newFileCursor
|
||||
@@ -198,7 +213,7 @@ function newPlotter () {
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] setTimePeriod -> err = ' + err.stack) }
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] setTimeFrame -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +221,12 @@ function newPlotter () {
|
||||
datetime = pDatetime
|
||||
}
|
||||
|
||||
function setCoordinateSystem (pCoordinateSystem) {
|
||||
finalizeCoordinateSystem()
|
||||
coordinateSystem = pCoordinateSystem
|
||||
initializeCoordinateSystem()
|
||||
}
|
||||
|
||||
function onDailyFileLoaded (event) {
|
||||
try {
|
||||
if (event.currentValue === event.totalValue) {
|
||||
@@ -219,7 +240,7 @@ function newPlotter () {
|
||||
|
||||
function draw () {
|
||||
try {
|
||||
this.container.frame.draw()
|
||||
thisObject.container.frame.draw()
|
||||
plotChart()
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] draw -> err = ' + err.stack) }
|
||||
@@ -228,7 +249,7 @@ function newPlotter () {
|
||||
|
||||
function recalculate () {
|
||||
try {
|
||||
if (timePeriod >= _1_HOUR_IN_MILISECONDS) {
|
||||
if (timeFrame >= _1_HOUR_IN_MILISECONDS) {
|
||||
recalculateUsingMarketFiles()
|
||||
} else {
|
||||
recalculateUsingDailyFiles()
|
||||
@@ -257,7 +278,10 @@ function newPlotter () {
|
||||
}
|
||||
}
|
||||
|
||||
if (record.begin >= farLeftDate.valueOf() && record.end <= farRightDate.valueOf()) {
|
||||
if (
|
||||
(record.begin >= farLeftDate.valueOf() && record.end <= farRightDate.valueOf()) &&
|
||||
(record.end >= coordinateSystem.min.x && record.begin <= coordinateSystem.max.x)
|
||||
) {
|
||||
record.previous = previous
|
||||
jsonifiedArray.push(record)
|
||||
previous = record
|
||||
@@ -272,14 +296,14 @@ function newPlotter () {
|
||||
return jsonifiedArray
|
||||
}
|
||||
|
||||
function calculationsProcedure (jsonArray, recordDefinition, calculationsProcedure, timePeriod) {
|
||||
function calculationsProcedure (jsonArray, recordDefinition, calculationsProcedure, timeFrame) {
|
||||
/*
|
||||
This function has as an input an array of JSON objects, and it adds calculated properties to
|
||||
complete the set of properties that will be available.
|
||||
*/
|
||||
|
||||
let system = { // These are the available system variables to be used in User Code and Formulas
|
||||
timePeriod: timePeriod,
|
||||
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.
|
||||
@@ -348,10 +372,10 @@ function newPlotter () {
|
||||
if (fileCursor === undefined) { return } // We need to wait until there is a fileCursor
|
||||
if (fileCursor.files.size === 0) { return } // We need to wait until there are files in the cursor
|
||||
|
||||
let daysOnSides = getSideDays(timePeriod)
|
||||
let daysOnSides = getSideDays(timeFrame)
|
||||
|
||||
let leftDate = getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem)
|
||||
let rightDate = getDateFromPoint(viewPort.visibleArea.topRight, thisObject.container, timeLineCoordinateSystem)
|
||||
let leftDate = getDateFromPoint(canvas.chartSpace.viewport.visibleArea.topLeft, thisObject.container, coordinateSystem)
|
||||
let rightDate = getDateFromPoint(canvas.chartSpace.viewport.visibleArea.topRight, thisObject.container, coordinateSystem)
|
||||
|
||||
let dateDiff = rightDate.valueOf() - leftDate.valueOf()
|
||||
|
||||
@@ -373,7 +397,7 @@ function newPlotter () {
|
||||
|
||||
/* Add the calculated properties */
|
||||
if (productDefinition.calculations !== undefined) {
|
||||
let calculationsResult = calculationsProcedure(jsonData, productDefinition.record, productDefinition.calculations, timePeriod)
|
||||
let calculationsResult = calculationsProcedure(jsonData, productDefinition.record, productDefinition.calculations, timeFrame)
|
||||
records.push(...calculationsResult) // This adds records to the current array.
|
||||
} else {
|
||||
records.push(...jsonData)// This adds records to the current array.
|
||||
@@ -401,10 +425,10 @@ function newPlotter () {
|
||||
try {
|
||||
if (marketFile === undefined) { return } // Initialization not complete yet.
|
||||
|
||||
let daysOnSides = getSideDays(timePeriod)
|
||||
let daysOnSides = getSideDays(timeFrame)
|
||||
|
||||
let leftDate = getDateFromPoint(viewPort.visibleArea.topLeft, thisObject.container, timeLineCoordinateSystem)
|
||||
let rightDate = getDateFromPoint(viewPort.visibleArea.topRight, thisObject.container, timeLineCoordinateSystem)
|
||||
let leftDate = getDateFromPoint(canvas.chartSpace.viewport.visibleArea.topLeft, thisObject.container, coordinateSystem)
|
||||
let rightDate = getDateFromPoint(canvas.chartSpace.viewport.visibleArea.topRight, thisObject.container, coordinateSystem)
|
||||
|
||||
let dateDiff = rightDate.valueOf() - leftDate.valueOf()
|
||||
|
||||
@@ -426,7 +450,7 @@ function newPlotter () {
|
||||
|
||||
/* Add the calculated properties */
|
||||
if (productDefinition.calculations !== undefined) {
|
||||
let calculationsResult = calculationsProcedure(jsonData, productDefinition.record, productDefinition.calculations, timePeriod)
|
||||
let calculationsResult = calculationsProcedure(jsonData, productDefinition.record, productDefinition.calculations, timeFrame)
|
||||
records.push(...calculationsResult) // This adds records to the current array.
|
||||
} else {
|
||||
records.push(...jsonData)// This adds records to the current array.
|
||||
@@ -438,7 +462,7 @@ function newPlotter () {
|
||||
|
||||
function recalculateScale () {
|
||||
try {
|
||||
if (timeLineCoordinateSystem.maxValue > 0) { return } // Already calculated.
|
||||
if (coordinateSystem.maxValue > 0) { return } // Already calculated.
|
||||
/* First we calculate the default scale */
|
||||
let minValue = {
|
||||
x: MIN_PLOTABLE_DATE.valueOf(),
|
||||
@@ -447,32 +471,15 @@ function newPlotter () {
|
||||
|
||||
let maxValue = {
|
||||
x: MAX_PLOTABLE_DATE.valueOf(),
|
||||
y: nextPorwerOf10(USDT_BTC_HTH) / 4 // TODO: This 4 is temporary
|
||||
y: nextPorwerOf10(MAX_DEFAULT_RATE_SCALE_VALUE) / 4 // TODO: This 4 is temporary
|
||||
}
|
||||
|
||||
timeLineCoordinateSystem.initialize(
|
||||
coordinateSystem.initialize(
|
||||
minValue,
|
||||
maxValue,
|
||||
thisObject.container.frame.width,
|
||||
thisObject.container.frame.height
|
||||
)
|
||||
|
||||
/* In case the plotter is configured to a certain slot, we calculate the slot coordinate system too. */
|
||||
if (productDefinition.referenceParent.code === undefined) { return }
|
||||
plotterModuleConfig = JSON.parse(productDefinition.referenceParent.code)
|
||||
if (plotterModuleConfig.slot === undefined) { return }
|
||||
|
||||
slotCoordinateSystem = newTimeLineCoordinateSystem()
|
||||
|
||||
minValue.y = plotterModuleConfig.slot.minValue
|
||||
maxValue.y = plotterModuleConfig.slot.maxValue
|
||||
|
||||
slotCoordinateSystem.initialize(
|
||||
minValue,
|
||||
maxValue,
|
||||
thisObject.container.frame.width,
|
||||
slotHeight
|
||||
)
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] recalculateScale -> err = ' + err.stack) }
|
||||
}
|
||||
@@ -480,9 +487,6 @@ function newPlotter () {
|
||||
|
||||
function plotChart () {
|
||||
try {
|
||||
let userPosition = getUserPosition()
|
||||
let userPositionDate = userPosition.point.x
|
||||
|
||||
/* Clean the pannel at places where there is no record. */
|
||||
let currentRecord = {
|
||||
data: undefined
|
||||
@@ -508,13 +512,19 @@ function newPlotter () {
|
||||
y: 0
|
||||
}
|
||||
|
||||
beginPoint = timeLineCoordinateSystem.transformThisPoint(beginPoint)
|
||||
endPoint = timeLineCoordinateSystem.transformThisPoint(endPoint)
|
||||
beginPoint = coordinateSystem.transformThisPoint(beginPoint)
|
||||
endPoint = coordinateSystem.transformThisPoint(endPoint)
|
||||
|
||||
beginPoint = transformThisPoint(beginPoint, thisObject.container)
|
||||
endPoint = transformThisPoint(endPoint, thisObject.container)
|
||||
|
||||
if (endPoint.x < viewPort.visibleArea.bottomLeft.x || beginPoint.x > viewPort.visibleArea.bottomRight.x) {
|
||||
beginPoint = canvas.chartSpace.viewport.fitIntoVisibleArea(beginPoint)
|
||||
endPoint = canvas.chartSpace.viewport.fitIntoVisibleArea(endPoint)
|
||||
|
||||
beginPoint = thisObject.fitFunction(beginPoint)
|
||||
endPoint = thisObject.fitFunction(endPoint)
|
||||
|
||||
if (endPoint.x < canvas.chartSpace.viewport.visibleArea.bottomLeft.x || beginPoint.x > canvas.chartSpace.viewport.visibleArea.bottomRight.x) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -562,14 +572,10 @@ function newPlotter () {
|
||||
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 = timeLineCoordinateSystem.transformThisPoint(dataPoint)
|
||||
|
||||
/*
|
||||
The browser canvas object does not care about our timeline and its coordinate system. In order to draw on a html canvas we
|
||||
need the points to be converted into the canvas coordinate system.
|
||||
Next we transform again to the screen coordinate system.
|
||||
*/
|
||||
dataPoint = coordinateSystem.transformThisPoint(dataPoint)
|
||||
dataPoint = transformThisPoint(dataPoint, thisObject.container)
|
||||
dataPoint = canvas.chartSpace.viewport.fitIntoVisibleArea(dataPoint)
|
||||
dataPoint = thisObject.fitFunction(dataPoint)
|
||||
|
||||
/* Store the data point at the local map */
|
||||
dataPoints.set(point.id, dataPoint)
|
||||
@@ -577,7 +583,7 @@ function newPlotter () {
|
||||
if (plotterModuleConfig !== undefined) {
|
||||
if (plotterModuleConfig.slot !== undefined) {
|
||||
/* We reset the y coordinate since it will be transformed with another coordinate system to fit into a slot. */
|
||||
dataPoint.y = (-1) * y * slotCoordinateSystem.scale.y + (plotterModuleConfig.slot.number - 1) * slotHeight + viewPort.visibleArea.topLeft.y
|
||||
dataPoint.y = (-1) * y * coordinateSystem.scale.y + (plotterModuleConfig.slot.number - 1) * slotHeight + canvas.chartSpace.viewport.visibleArea.topLeft.y
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -717,7 +723,7 @@ function newPlotter () {
|
||||
y: dataPointObject.y
|
||||
}
|
||||
/* We make sure the points do not fall outside the viewport visible area. This step allways need to be done. */
|
||||
dataPoint = viewPort.fitIntoVisibleArea(dataPoint)
|
||||
dataPoint = canvas.chartSpace.viewport.fitIntoVisibleArea(dataPoint)
|
||||
if (k === 0) {
|
||||
browserCanvasContext.moveTo(dataPoint.x, dataPoint.y)
|
||||
} else {
|
||||
@@ -766,12 +772,12 @@ function newPlotter () {
|
||||
}
|
||||
}
|
||||
|
||||
function onZoomChanged (event) {
|
||||
function onViewportZoomChanged (event) {
|
||||
try {
|
||||
mustRecalculateDataPoints = true
|
||||
recalculate()
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] onZoomChanged -> err = ' + err.stack) }
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] onViewportZoomChanged -> err = ' + err.stack) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,20 +789,24 @@ function newPlotter () {
|
||||
}
|
||||
}
|
||||
|
||||
function onOffsetChanged (event) {
|
||||
try {
|
||||
mustRecalculateDataPoints = true
|
||||
if (event !== undefined) {
|
||||
if (event.recalculate === true) {
|
||||
recalculate()
|
||||
return
|
||||
}
|
||||
}
|
||||
if (Math.random() * 100 > 95) {
|
||||
function onDisplace (event) {
|
||||
recalculateAll(event)
|
||||
}
|
||||
|
||||
function onViewportPositionChanged (event) {
|
||||
recalculateAll(event)
|
||||
}
|
||||
|
||||
function recalculateAll (event) {
|
||||
mustRecalculateDataPoints = true
|
||||
if (event !== undefined) {
|
||||
if (event.recalculate === true) {
|
||||
recalculate()
|
||||
};
|
||||
} catch (err) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] onOffsetChanged -> err = ' + err.stack) }
|
||||
return
|
||||
}
|
||||
}
|
||||
if (Math.random() * 100 > 95) {
|
||||
recalculate()
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-21
@@ -1,5 +1,5 @@
|
||||
|
||||
function newProductStorage (pName) {
|
||||
function newProductStorage (name) {
|
||||
const MODULE_NAME = 'Product Storage'
|
||||
const ERROR_LOG = true
|
||||
const logger = newWebDebugLog()
|
||||
@@ -31,7 +31,7 @@ function newProductStorage (pName) {
|
||||
singleFile: [],
|
||||
fileSequences: [],
|
||||
setDatetime: setDatetime,
|
||||
setTimePeriod: setTimePeriod,
|
||||
setTimeFrame: setTimeFrame,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
@@ -40,10 +40,10 @@ function newProductStorage (pName) {
|
||||
|
||||
/* We name the event Handler to easy debugging. */
|
||||
|
||||
thisObject.eventHandler.name = 'Storage-' + pName
|
||||
thisObject.eventHandler.name = 'Storage-' + name
|
||||
|
||||
let datetime
|
||||
let timePeriod
|
||||
let timeFrame
|
||||
|
||||
return thisObject
|
||||
|
||||
@@ -74,23 +74,23 @@ function newProductStorage (pName) {
|
||||
}
|
||||
}
|
||||
|
||||
function initialize (pDevTeam, pBot, pSession, pProduct, pExchange, pMarket, pDatetime, pTimePeriod, callBackFunction) {
|
||||
function initialize (dataMine, bot, session, product, exchange, market, pDatetime, pTimeFrame, callBackFunction) {
|
||||
try {
|
||||
datetime = pDatetime
|
||||
timePeriod = pTimePeriod
|
||||
timeFrame = pTimeFrame
|
||||
|
||||
let dataSetsToLoad = 0
|
||||
let dataSetsLoaded = 0
|
||||
|
||||
for (let i = 0; i < pProduct.dataSets.length; i++) {
|
||||
let thisSet = pProduct.dataSets[i]
|
||||
for (let i = 0; i < product.datasets.length; i++) {
|
||||
let dataset = product.datasets[i]
|
||||
|
||||
switch (thisSet.type) {
|
||||
switch (dataset.code.type) {
|
||||
case 'Market Files': {
|
||||
dataSetsToLoad++
|
||||
|
||||
let marketFiles = newMarketFiles()
|
||||
marketFiles.initialize(pDevTeam, pBot, pSession, pProduct, thisSet, pExchange, pMarket, onMarketFileReady)
|
||||
marketFiles.initialize(dataMine, bot, session, product, dataset, exchange, market, onMarketFileReady)
|
||||
thisObject.marketFiles.push(marketFiles)
|
||||
}
|
||||
break
|
||||
@@ -99,7 +99,7 @@ function newProductStorage (pName) {
|
||||
dataSetsToLoad++
|
||||
|
||||
let dailyFiles = newDailyFiles()
|
||||
dailyFiles.initialize(pDevTeam, pBot, pSession, pProduct, thisSet, pExchange, pMarket, pDatetime, pTimePeriod, onDailyFileReady)
|
||||
dailyFiles.initialize(dataMine, bot, session, product, dataset, exchange, market, pDatetime, pTimeFrame, onDailyFileReady)
|
||||
thisObject.dailyFiles.push(dailyFiles)
|
||||
}
|
||||
break
|
||||
@@ -108,7 +108,7 @@ function newProductStorage (pName) {
|
||||
dataSetsToLoad++
|
||||
|
||||
let singleFile = newSingleFile()
|
||||
singleFile.initialize(pDevTeam, pBot, pSession, pProduct, thisSet, pExchange, pMarket, onSingleFileReady)
|
||||
singleFile.initialize(dataMine, bot, session, product, dataset, exchange, market, onSingleFileReady)
|
||||
thisObject.singleFile.push(singleFile)
|
||||
}
|
||||
break
|
||||
@@ -117,12 +117,12 @@ function newProductStorage (pName) {
|
||||
dataSetsToLoad++
|
||||
|
||||
let fileSequences = newFileSequence()
|
||||
fileSequences.initialize(pDevTeam, pBot, pSession, pProduct, thisSet, pExchange, pMarket, onFileSequenceReady)
|
||||
fileSequences.initialize(dataMine, bot, session, product, dataset, exchange, market, onFileSequenceReady)
|
||||
thisObject.fileSequences.push(fileSequences)
|
||||
}
|
||||
break
|
||||
default:
|
||||
if (ERROR_LOG === true) { logger.write('[WARN] initialize -> initialize -> dataset with no type defined. Data can not be retrieved. -> codeName = ' + thisSet.codeName) }
|
||||
if (ERROR_LOG === true) { logger.write('[WARN] initialize -> dataset with no type defined or type not supported -> dataset.code.type = ' + dataset.code.type) }
|
||||
}
|
||||
|
||||
function onMarketFileReady (err, pCaller) {
|
||||
@@ -309,7 +309,7 @@ function newProductStorage (pName) {
|
||||
datetime = new Date(pDatetime)
|
||||
|
||||
if (currentDate !== newDate) {
|
||||
if (timePeriod <= _1_HOUR_IN_MILISECONDS) {
|
||||
if (timeFrame <= _1_HOUR_IN_MILISECONDS) {
|
||||
for (let i = 0; i < thisObject.dailyFiles.length; i++) {
|
||||
thisObject.dailyFiles[i].setDatetime(pDatetime)
|
||||
}
|
||||
@@ -317,15 +317,15 @@ function newProductStorage (pName) {
|
||||
}
|
||||
}
|
||||
|
||||
function setTimePeriod (pTimePeriod) {
|
||||
/* We are going to filter out the cases in which the timePeriod received is the same that the one we already know. */
|
||||
function setTimeFrame (pTimeFrame) {
|
||||
/* We are going to filter out the cases in which the timeFrame received is the same that the one we already know. */
|
||||
|
||||
if (timePeriod !== pTimePeriod) {
|
||||
timePeriod = pTimePeriod
|
||||
if (timeFrame !== pTimeFrame) {
|
||||
timeFrame = pTimeFrame
|
||||
|
||||
if (timePeriod <= _1_HOUR_IN_MILISECONDS) {
|
||||
if (timeFrame <= _1_HOUR_IN_MILISECONDS) {
|
||||
for (let i = 0; i < thisObject.dailyFiles.length; i++) {
|
||||
thisObject.dailyFiles[i].setTimePeriod(pTimePeriod, datetime)
|
||||
thisObject.dailyFiles[i].setTimeFrame(pTimeFrame, datetime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -106,7 +106,7 @@
|
||||
<Compile Include="TopSpace\CurrentEvent.js">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TopSpace\DevTeam.js">
|
||||
<Compile Include="TopSpace\dataMine.js">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="TopSpace\EndUser.js">
|
||||
@@ -127,7 +127,7 @@
|
||||
<Compile Include="Spaces\PanelsSpace.js">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ProductCard.js">
|
||||
<Compile Include="Layer.js">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Files\SingleFile.js">
|
||||
@@ -156,9 +156,9 @@
|
||||
<Compile Include="EventHandler.js" />
|
||||
<Compile Include="Spaces\FloatingSpace.js" />
|
||||
<Compile Include="Frame.js" />
|
||||
<Compile Include="Panels\ProductsPanel.js" />
|
||||
<Compile Include="Panels\LayersPanel.js" />
|
||||
<Compile Include="Panels\TimeControlPanel.js" />
|
||||
<Compile Include="TimeLineCoordinateSystem.js" />
|
||||
<Compile Include="coordinateSystem.js" />
|
||||
<Compile Include="SplashScreen.js">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Welcome to the Canvas App
|
||||
|
||||
The Canvas App provides a visual environment for the _Charting System_ and the _Designer_.
|
||||
The Canvas App provides a visual environment for the _Charting Space_ and the _Designer_.
|
||||
|
||||
**Installation (for developers):** To install the Canvas App, you need to install AAWeb, following [this guide](https://github.com/Superalgos/AAWeb/blob/develop/README.md).
|
||||
|
||||
|
||||
+25
-36
@@ -1,56 +1,45 @@
|
||||
|
||||
function drawScaleDisplay (label1, label2, xExtraOffSet1, xExtraOffSet2, container, fitFunction) {
|
||||
let fontSize1 = 20
|
||||
let fontSize2 = 10
|
||||
|
||||
const RED_LINE_HIGHT = 5
|
||||
function drawScaleDisplay (label1, label2, label3, xExtraOffSet1, xExtraOffSet2, xExtraOffSet3, icon1, icon2, container, backgroundColor) {
|
||||
const RED_LINE_HIGHT = 4
|
||||
const OPACITY = 1
|
||||
|
||||
let params = {
|
||||
cornerRadius: 3,
|
||||
lineWidth: RED_LINE_HIGHT,
|
||||
cornerRadius: 5,
|
||||
lineWidth: 1,
|
||||
container: container,
|
||||
borderColor: UI_COLOR.RUSTED_RED,
|
||||
castShadow: false,
|
||||
backgroundColor: UI_COLOR.DARK,
|
||||
opacity: OPACITY,
|
||||
fitFunction: fitFunction
|
||||
backgroundColor: backgroundColor,
|
||||
opacity: OPACITY
|
||||
}
|
||||
|
||||
roundedCornersBackground(params)
|
||||
|
||||
/* Place the Text */
|
||||
|
||||
let xOffset1 = label1.length * fontSize1 * FONT_ASPECT_RATIO
|
||||
label1 = label1.substring(0, 18)
|
||||
label2 = label2.substring(0, 20)
|
||||
label3 = label3.substring(0, 20)
|
||||
|
||||
let labelPoint1 = {
|
||||
x: container.frame.width / 2 - xOffset1 + xExtraOffSet1,
|
||||
y: container.frame.height / 2 + 6
|
||||
}
|
||||
drawLabel(label1, 1 / 2, 92 / 100, 0, 0, 9, container)
|
||||
drawLabel(label2, 1 / 2, 42 / 100, 0, 0, 17, container)
|
||||
drawLabel(label3, 1 / 2, 67 / 100, 0, 0, 9, container)
|
||||
|
||||
labelPoint1 = container.frame.frameThisPoint(labelPoint1)
|
||||
let x = labelPoint1.x
|
||||
labelPoint1 = fitFunction(labelPoint1)
|
||||
labelPoint1.x = x
|
||||
drawIcon(icon1, 1 / 8, 1 / 2, 0, 0, 28, container)
|
||||
drawIcon(icon2, 7 / 8, 1 / 2, 0, 0, 28, container)
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize1 + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
|
||||
browserCanvasContext.fillText(label1, labelPoint1.x, labelPoint1.y)
|
||||
|
||||
let xOffset2 = label2.length * fontSize2 * FONT_ASPECT_RATIO
|
||||
|
||||
let labelPoint2 = {
|
||||
x: container.frame.width / 2 - xOffset2 / 2 - 3 + xExtraOffSet2,
|
||||
y: container.frame.height / 2 + 6
|
||||
function drawScaleDisplayCover (container) {
|
||||
let params = {
|
||||
cornerRadius: 5,
|
||||
lineWidth: 1,
|
||||
container: container,
|
||||
borderColor: UI_COLOR.WHITE,
|
||||
castShadow: false,
|
||||
backgroundColor: UI_COLOR.WHITE,
|
||||
opacity: '0.25'
|
||||
}
|
||||
|
||||
labelPoint2 = container.frame.frameThisPoint(labelPoint2)
|
||||
labelPoint2 = fitFunction(labelPoint2)
|
||||
|
||||
browserCanvasContext.font = fontSize2 + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
|
||||
browserCanvasContext.fillText(label2, labelPoint2.x, labelPoint2.y)
|
||||
roundedCornersBackground(params)
|
||||
}
|
||||
|
||||
+384
-55
@@ -5,18 +5,34 @@ function newRateScale () {
|
||||
container: undefined,
|
||||
rate: undefined,
|
||||
fitFunction: undefined,
|
||||
visible: true,
|
||||
heightPercentage: 150,
|
||||
payload: undefined,
|
||||
scale: undefined,
|
||||
offset: undefined,
|
||||
minValue: undefined,
|
||||
maxValue: undefined,
|
||||
isVisible: true,
|
||||
layersOn: undefined,
|
||||
setScale: setScale,
|
||||
onMouseOverSomeTimeMachineContainer: onMouseOverSomeTimeMachineContainer,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
drawForeground: drawForeground,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
const HEIGHT_PERCENTAGE_DEFAULT_VALUE = 50
|
||||
const STEP_SIZE = 2
|
||||
const MIN_WIDTH = 50
|
||||
const DEFAULT_SCALE = 50
|
||||
const STEP_SCALE = 1
|
||||
const MIN_SCALE = 0
|
||||
const MAX_SCALE = 100
|
||||
const SNAP_THRESHOLD_SCALE = 1
|
||||
|
||||
const DEFAULT_OFFSET = 0
|
||||
const STEP_OFFSET = 1
|
||||
const MIN_OFFSET = -1000
|
||||
const MAX_OFFSET = 1000
|
||||
const SNAP_THRESHOLD_OFFSET = 3
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME)
|
||||
@@ -26,56 +42,167 @@ function newRateScale () {
|
||||
thisObject.container.isWheelable = true
|
||||
thisObject.container.detectMouseOver = true
|
||||
|
||||
thisObject.container.frame.width = 110
|
||||
thisObject.container.frame.height = 25
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL
|
||||
thisObject.container.frame.height = 40
|
||||
|
||||
thisObject.offset = DEFAULT_OFFSET
|
||||
|
||||
let visible = true
|
||||
let isMouseOver
|
||||
|
||||
let onMouseWheelEventSubscriptionId
|
||||
let onMouseOverEventSubscriptionId
|
||||
let onMouseNotOverEventSubscriptionId
|
||||
|
||||
let coordinateSystem
|
||||
let limitingContainer
|
||||
let rateCalculationsContainer
|
||||
|
||||
let mouse = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
|
||||
let offsetTimer = 0
|
||||
let scaleTimer = 0
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseWheelEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.payload = undefined
|
||||
|
||||
coordinateSystem = undefined
|
||||
limitingContainer = undefined
|
||||
rateCalculationsContainer = undefined
|
||||
mouse = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
function initialize (pCoordinateSystem, pLimitingContainer, pRateCalculationsContainer) {
|
||||
coordinateSystem = pCoordinateSystem
|
||||
limitingContainer = pLimitingContainer
|
||||
rateCalculationsContainer = pRateCalculationsContainer
|
||||
|
||||
thisObject.heightPercentage = window.localStorage.getItem(MODULE_NAME)
|
||||
if (!thisObject.heightPercentage) {
|
||||
thisObject.heightPercentage = HEIGHT_PERCENTAGE_DEFAULT_VALUE
|
||||
} else {
|
||||
thisObject.heightPercentage = JSON.parse(thisObject.heightPercentage)
|
||||
}
|
||||
thisObject.minValue = coordinateSystem.min.y
|
||||
thisObject.maxValue = coordinateSystem.max.y
|
||||
|
||||
onMouseWheelEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
|
||||
thisObject.scale = DEFAULT_SCALE
|
||||
readObjectState()
|
||||
|
||||
let event = {}
|
||||
event.heightPercentage = thisObject.heightPercentage
|
||||
thisObject.container.eventHandler.raiseEvent('Height Percentage Changed', event)
|
||||
event.scale = thisObject.scale
|
||||
thisObject.container.eventHandler.raiseEvent('Rate Scale Value Changed', event)
|
||||
}
|
||||
|
||||
function onMouseOver () {
|
||||
function onMouseOverSomeTimeMachineContainer (event) {
|
||||
if (event.containerId === undefined) {
|
||||
/* This happens when the mouse over was not at the instance of a certain scale, but anywhere else. */
|
||||
visible = true
|
||||
} else {
|
||||
if (event.containerId === thisObject.container.id) {
|
||||
visible = true
|
||||
} else {
|
||||
visible = false
|
||||
turnOnCounter = 0
|
||||
}
|
||||
}
|
||||
mouse = {
|
||||
position: {
|
||||
x: event.x,
|
||||
y: event.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
isMouseOver = true
|
||||
event.containerId = thisObject.container.id
|
||||
thisObject.container.eventHandler.raiseEvent('onMouseOverScale', event)
|
||||
}
|
||||
|
||||
function onMouseNotOver () {
|
||||
isMouseOver = false
|
||||
offsetTimer = 0
|
||||
scaleTimer = 0
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
delta = event.wheelDelta
|
||||
if (delta < 0) {
|
||||
thisObject.heightPercentage = thisObject.heightPercentage - STEP_SIZE
|
||||
if (thisObject.heightPercentage < STEP_SIZE) { thisObject.heightPercentage = STEP_SIZE }
|
||||
} else {
|
||||
thisObject.heightPercentage = thisObject.heightPercentage + STEP_SIZE
|
||||
if (thisObject.heightPercentage > 150) { thisObject.heightPercentage = 200 }
|
||||
}
|
||||
event.heightPercentage = thisObject.heightPercentage
|
||||
thisObject.container.eventHandler.raiseEvent('Height Percentage Changed', event)
|
||||
let morePower = 1
|
||||
let delta
|
||||
|
||||
window.localStorage.setItem(MODULE_NAME, thisObject.heightPercentage)
|
||||
if (event.shiftKey === true) {
|
||||
if (event.buttons === 4) { morePower = 10 } // Mouse wheel pressed.
|
||||
delta = event.wheelDelta
|
||||
if (delta < 0) {
|
||||
thisObject.offset = thisObject.offset - STEP_OFFSET * morePower
|
||||
if (thisObject.offset < MIN_OFFSET) { thisObject.offset = STEP_OFFSET }
|
||||
} else {
|
||||
thisObject.offset = thisObject.offset + STEP_OFFSET * morePower
|
||||
if (thisObject.offset > MAX_OFFSET) { thisObject.offset = MAX_OFFSET }
|
||||
}
|
||||
|
||||
if (
|
||||
thisObject.offset <= DEFAULT_OFFSET + SNAP_THRESHOLD_OFFSET &&
|
||||
thisObject.offset >= DEFAULT_OFFSET - SNAP_THRESHOLD_OFFSET
|
||||
) {
|
||||
event.offset = 0
|
||||
} else {
|
||||
event.offset = -thisObject.offset
|
||||
}
|
||||
|
||||
event.isUserAction = true
|
||||
thisObject.container.eventHandler.raiseEvent('Rate Scale Offset Changed', event)
|
||||
|
||||
saveObjectState()
|
||||
offsetTimer = 100
|
||||
scaleTimer = 0
|
||||
} else {
|
||||
if (event.buttons === 4) { morePower = 5 } // Mouse wheel pressed.
|
||||
delta = event.wheelDelta
|
||||
if (delta < 0) {
|
||||
thisObject.scale = thisObject.scale - STEP_SCALE * morePower
|
||||
if (thisObject.scale < MIN_SCALE) { thisObject.scale = MIN_SCALE }
|
||||
} else {
|
||||
thisObject.scale = thisObject.scale + STEP_SCALE * morePower
|
||||
if (thisObject.scale > MAX_SCALE) { thisObject.scale = MAX_SCALE }
|
||||
}
|
||||
|
||||
finishScaleChange(event)
|
||||
}
|
||||
}
|
||||
|
||||
function setScale (scale) {
|
||||
thisObject.scale = scale
|
||||
let event = {}
|
||||
finishScaleChange(event)
|
||||
}
|
||||
|
||||
function finishScaleChange (event) {
|
||||
if (
|
||||
thisObject.scale <= DEFAULT_SCALE + SNAP_THRESHOLD_SCALE &&
|
||||
thisObject.scale >= DEFAULT_SCALE - SNAP_THRESHOLD_SCALE
|
||||
) {
|
||||
event.scale = DEFAULT_SCALE
|
||||
} else {
|
||||
event.scale = thisObject.scale
|
||||
}
|
||||
event.isUserAction = true
|
||||
thisObject.container.eventHandler.raiseEvent('Rate Scale Value Changed', event)
|
||||
|
||||
saveObjectState()
|
||||
offsetTimer = 0
|
||||
scaleTimer = 100
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
@@ -84,18 +211,232 @@ function newRateScale () {
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
function saveObjectState () {
|
||||
try {
|
||||
let code = JSON.parse(thisObject.payload.node.code)
|
||||
code.scale = thisObject.scale / MAX_SCALE * 100
|
||||
code.scale = code.scale.toFixed(0)
|
||||
code.offset = thisObject.offset
|
||||
code.minValue = thisObject.minValue
|
||||
code.maxValue = thisObject.maxValue
|
||||
thisObject.payload.node.code = JSON.stringify(code, null, 4)
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
}
|
||||
|
||||
function readObjectState () {
|
||||
try {
|
||||
let code = JSON.parse(thisObject.payload.node.code)
|
||||
|
||||
if (isNaN(code.scale) || code.scale === null || code.scale === undefined) {
|
||||
// not using this value
|
||||
} else {
|
||||
code.scale = code.scale / 100 * MAX_SCALE
|
||||
if (code.scale < MIN_SCALE) { code.scale = MIN_SCALE }
|
||||
if (code.scale > MAX_SCALE) { code.scale = MAX_SCALE }
|
||||
|
||||
if (code.scale !== thisObject.scale) {
|
||||
thisObject.scale = code.scale
|
||||
let event = {}
|
||||
if (
|
||||
thisObject.scale <= DEFAULT_SCALE + SNAP_THRESHOLD_SCALE &&
|
||||
thisObject.scale >= DEFAULT_SCALE - SNAP_THRESHOLD_SCALE
|
||||
) {
|
||||
event.scale = DEFAULT_SCALE
|
||||
} else {
|
||||
event.scale = thisObject.scale
|
||||
}
|
||||
thisObject.container.eventHandler.raiseEvent('Rate Scale Value Changed', event)
|
||||
}
|
||||
}
|
||||
|
||||
if (isNaN(code.offset) || code.offset === null || code.offset === undefined) {
|
||||
// not using this value
|
||||
} else {
|
||||
if (code.offset < MIN_OFFSET) { code.offset = MIN_OFFSET }
|
||||
if (code.offset > MAX_OFFSET) { code.offset = MAX_OFFSET }
|
||||
|
||||
if (code.offset !== thisObject.offset) {
|
||||
thisObject.offset = code.offset
|
||||
let event = {}
|
||||
if (
|
||||
thisObject.offset <= DEFAULT_OFFSET + SNAP_THRESHOLD_OFFSET &&
|
||||
thisObject.offset >= DEFAULT_OFFSET - SNAP_THRESHOLD_OFFSET
|
||||
) {
|
||||
event.offset = 0
|
||||
} else {
|
||||
event.offset = -thisObject.offset
|
||||
}
|
||||
thisObject.container.eventHandler.raiseEvent('Rate Scale Offset Changed', event)
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(isNaN(code.minValue) || code.minValue === null || code.minValue === undefined) ||
|
||||
(isNaN(code.maxValue) || code.maxValue === null || code.maxValue === undefined)
|
||||
) {
|
||||
// not using this value
|
||||
} else {
|
||||
if (thisObject.minValue !== code.minValue || thisObject.maxValue !== code.maxValue) {
|
||||
thisObject.minValue = code.minValue
|
||||
thisObject.maxValue = code.maxValue
|
||||
coordinateSystem.min.y = thisObject.minValue
|
||||
coordinateSystem.max.y = thisObject.maxValue
|
||||
coordinateSystem.recalculateScale()
|
||||
}
|
||||
}
|
||||
saveObjectState() // this overrides any invalid value at the config.
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
offsetTimer--
|
||||
scaleTimer--
|
||||
readObjectState()
|
||||
positioningPhysics()
|
||||
}
|
||||
|
||||
function positioningPhysics () {
|
||||
/* Container Limits */
|
||||
|
||||
let upCorner = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let bottonCorner = {
|
||||
x: limitingContainer.frame.width,
|
||||
y: limitingContainer.frame.height
|
||||
}
|
||||
|
||||
upCorner = transformThisPoint(upCorner, limitingContainer)
|
||||
bottonCorner = transformThisPoint(bottonCorner, limitingContainer)
|
||||
|
||||
upCorner = limitingContainer.fitFunction(upCorner, true)
|
||||
bottonCorner = limitingContainer.fitFunction(bottonCorner, true)
|
||||
|
||||
/* We will check if we need to change the bottom because of being one of many scales of the same type */
|
||||
let displaceFactor = 0
|
||||
if (thisObject.payload.parentNode === undefined) { return } // This happens when in the process of deleting the scale, timeline chart or time machine.
|
||||
if (thisObject.payload.parentNode.type === 'Timeline Chart') {
|
||||
if (thisObject.payload.parentNode.payload.parentNode !== undefined) {
|
||||
if (thisObject.payload.parentNode.payload.parentNode.rateScale !== undefined) {
|
||||
if (thisObject.payload.parentNode.payload.parentNode.rateScale.payload.isVisible === true) {
|
||||
displaceFactor++
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < thisObject.payload.parentNode.payload.parentNode.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.payload.parentNode.payload.parentNode.timelineCharts[i]
|
||||
if (timelineChart.rateScale !== undefined) {
|
||||
if (thisObject.payload.node.id !== timelineChart.rateScale.id) {
|
||||
if (timelineChart.rateScale.payload.isVisible === true) {
|
||||
displaceFactor++
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bottonCorner.x = bottonCorner.x - thisObject.container.frame.width * displaceFactor
|
||||
|
||||
/* Mouse Position Rate Calculation */
|
||||
let ratePoint = {
|
||||
x: 0,
|
||||
y: mouse.position.y + thisObject.offset
|
||||
}
|
||||
|
||||
thisObject.rate = getRateFromPoint(ratePoint, rateCalculationsContainer, coordinateSystem)
|
||||
|
||||
/* rateScale Positioning */
|
||||
ratePoint = {
|
||||
x: limitingContainer.frame.width,
|
||||
y: 0
|
||||
}
|
||||
|
||||
ratePoint = transformThisPoint(ratePoint, limitingContainer.frame.container)
|
||||
ratePoint.y = mouse.position.y - thisObject.container.frame.height / 2 + thisObject.container.frame.height
|
||||
|
||||
/* Checking against the container limits. */
|
||||
if (ratePoint.x < upCorner.x) { ratePoint.x = upCorner.x }
|
||||
if (ratePoint.x + thisObject.container.frame.width > bottonCorner.x) { ratePoint.x = bottonCorner.x }
|
||||
if (ratePoint.y < upCorner.y + thisObject.container.frame.height) { ratePoint.y = upCorner.y + thisObject.container.frame.height }
|
||||
if (ratePoint.y > bottonCorner.y) { ratePoint.y = bottonCorner.y }
|
||||
|
||||
thisObject.container.frame.position.y = ratePoint.y - thisObject.container.frame.height
|
||||
thisObject.container.frame.position.x = ratePoint.x - thisObject.container.frame.width
|
||||
|
||||
thisObject.isVisible = true
|
||||
thisObject.payload.isVisible = true
|
||||
if (thisObject.container.frame.position.y + thisObject.container.frame.height * 2 > bottonCorner.y ||
|
||||
thisObject.container.frame.position.y - thisObject.container.frame.height * 1 < upCorner.y ||
|
||||
thisObject.container.frame.position.x < upCorner.x
|
||||
) {
|
||||
thisObject.isVisible = false
|
||||
thisObject.payload.isVisible = false
|
||||
}
|
||||
if (thisObject.layersOn === 0) {
|
||||
thisObject.isVisible = false
|
||||
thisObject.payload.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
drawRate()
|
||||
drawArrows()
|
||||
drawScaleBox()
|
||||
if (visible === false) {
|
||||
drawScaleDisplayCover(thisObject.container)
|
||||
}
|
||||
}
|
||||
|
||||
function drawForeground () {
|
||||
if (isMouseOver === true) {
|
||||
drawScaleBox()
|
||||
drawArrows()
|
||||
}
|
||||
}
|
||||
|
||||
function drawScaleBox () {
|
||||
if (thisObject.rate === undefined) { return }
|
||||
|
||||
let rate = thisObject.rate
|
||||
|
||||
if (rate < coordinateSystem.min.y) {
|
||||
rate = coordinateSystem.min.y
|
||||
}
|
||||
if (rate > coordinateSystem.max.y) {
|
||||
rate = coordinateSystem.max.y
|
||||
}
|
||||
|
||||
let label = (rate - Math.trunc(rate)).toFixed(2)
|
||||
let labelArray = label.split('.')
|
||||
let label1 = thisObject.payload.node.payload.parentNode.name
|
||||
let label2 = (Math.trunc(rate)).toLocaleString()
|
||||
let label3 = labelArray[1]
|
||||
|
||||
let icon1 = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.type)
|
||||
let icon2 = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
|
||||
if (offsetTimer > 0) {
|
||||
label2 = thisObject.offset.toFixed(0)
|
||||
label3 = 'OFFSET'
|
||||
}
|
||||
|
||||
if (scaleTimer > 0) {
|
||||
label2 = (thisObject.scale / MAX_SCALE * 100).toFixed(0)
|
||||
label3 = 'SCALE'
|
||||
}
|
||||
|
||||
drawScaleDisplay(label1, label2, label3, 0, 0, 0, icon1, icon2, thisObject.container, backgroundColor)
|
||||
}
|
||||
|
||||
function drawArrows () {
|
||||
if (isMouseOver !== true) { return }
|
||||
if (thisObject.visible === false || thisObject.rate === undefined) { return }
|
||||
if (visible === false || thisObject.rate === undefined) { return }
|
||||
|
||||
const X_OFFSET = thisObject.container.frame.width / 2
|
||||
const Y_OFFSET = thisObject.container.frame.height / 2
|
||||
@@ -105,7 +446,7 @@ function newRateScale () {
|
||||
const OPACITY = 0.2
|
||||
const DISTANCE_BETWEEN_ARROWS = 10
|
||||
const MIN_DISTANCE_FROM_CENTER = 30
|
||||
const CURRENT_VALUE_DISTANCE = MIN_DISTANCE_FROM_CENTER + thisObject.heightPercentage
|
||||
const CURRENT_SCALE_DISTANCE = MIN_DISTANCE_FROM_CENTER + thisObject.scale
|
||||
const MAX_DISTANCE_FROM_CENTER = MIN_DISTANCE_FROM_CENTER + 215 + DISTANCE_BETWEEN_ARROWS
|
||||
|
||||
let ARROW_DIRECTION = 0
|
||||
@@ -118,17 +459,17 @@ function newRateScale () {
|
||||
function drawTwoArrows () {
|
||||
point1 = {
|
||||
x: X_OFFSET - WIDTH / 2,
|
||||
y: Y_OFFSET + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION
|
||||
y: Y_OFFSET + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: X_OFFSET,
|
||||
y: Y_OFFSET + HEIGHT * ARROW_DIRECTION + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION
|
||||
y: Y_OFFSET + HEIGHT * ARROW_DIRECTION + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: X_OFFSET + WIDTH / 2,
|
||||
y: Y_OFFSET + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION
|
||||
y: Y_OFFSET + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION
|
||||
}
|
||||
|
||||
point1 = thisObject.container.frame.frameThisPoint(point1)
|
||||
@@ -137,17 +478,17 @@ function newRateScale () {
|
||||
|
||||
point4 = {
|
||||
x: X_OFFSET - WIDTH / 2,
|
||||
y: Y_OFFSET - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION
|
||||
y: Y_OFFSET - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION
|
||||
}
|
||||
|
||||
point5 = {
|
||||
x: X_OFFSET,
|
||||
y: Y_OFFSET + HEIGHT * ARROW_DIRECTION - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION
|
||||
y: Y_OFFSET + HEIGHT * ARROW_DIRECTION - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION
|
||||
}
|
||||
|
||||
point6 = {
|
||||
x: X_OFFSET + WIDTH / 2,
|
||||
y: Y_OFFSET - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION
|
||||
y: Y_OFFSET - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION
|
||||
}
|
||||
|
||||
point4 = thisObject.container.frame.frameThisPoint(point4)
|
||||
@@ -194,16 +535,4 @@ function newRateScale () {
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
function drawRate () {
|
||||
if (thisObject.visible === false || thisObject.rate === undefined) { return }
|
||||
|
||||
let label = (thisObject.rate - Math.trunc(thisObject.rate)).toFixed(2)
|
||||
let labelArray = label.split('.')
|
||||
let label1 = (Math.trunc(thisObject.rate)).toLocaleString()
|
||||
let label2 = labelArray[1]
|
||||
|
||||
drawScaleDisplay(label1, label2, 10, 40, thisObject.container, thisObject.fitFunction)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
function newTimeFrameScale () {
|
||||
const MODULE_NAME = 'Time Frame Scale'
|
||||
|
||||
let thisObject = {
|
||||
timeFrame: undefined,
|
||||
container: undefined,
|
||||
fitFunction: undefined,
|
||||
payload: undefined,
|
||||
isVisible: true,
|
||||
layersOn: undefined,
|
||||
onMouseOverSomeTimeMachineContainer: onMouseOverSomeTimeMachineContainer,
|
||||
draw: draw,
|
||||
drawForeground: drawForeground,
|
||||
physics: physics,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
const FILES_PERIOD_DEFAULT_VALUE = 0
|
||||
const TIME_PERIOD_DEFAULT_VALUE = 0
|
||||
const MIN_HEIGHT = 50
|
||||
|
||||
let visible = true
|
||||
let isMouseOver
|
||||
|
||||
let filePeriodIndex = FILES_PERIOD_DEFAULT_VALUE
|
||||
let timeFrameIndex = TIME_PERIOD_DEFAULT_VALUE
|
||||
let timeFramesMasterArray = [marketFilesPeriods, dailyFilePeriods]
|
||||
let timeFrameLabel = '24-hs'
|
||||
|
||||
let onMouseWheelEventSubscriptionId
|
||||
let onViewportZoomChangedEventSubscriptionId
|
||||
let onMouseOverEventSubscriptionId
|
||||
let onMouseNotOverEventSubscriptionId
|
||||
|
||||
let limitingContainer
|
||||
|
||||
let mouse = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
setupContainer()
|
||||
return thisObject
|
||||
|
||||
function setupContainer () {
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME)
|
||||
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.isClickeable = false
|
||||
thisObject.container.isWheelable = true
|
||||
thisObject.container.detectMouseOver = true
|
||||
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL
|
||||
thisObject.container.frame.height = 40
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseWheelEventSubscriptionId)
|
||||
canvas.chartSpace.viewport.eventHandler.stopListening(onViewportZoomChangedEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.payload = undefined
|
||||
|
||||
limitingContainer = undefined
|
||||
mouse = undefined
|
||||
}
|
||||
|
||||
function initialize (pLimitingContainer) {
|
||||
limitingContainer = pLimitingContainer
|
||||
|
||||
readObjectState()
|
||||
newTimeFrame()
|
||||
|
||||
onMouseWheelEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
onViewportZoomChangedEventSubscriptionId = canvas.chartSpace.viewport.eventHandler.listenToEvent('Zoom Changed', onViewportZoomChanged)
|
||||
onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
}
|
||||
|
||||
function onMouseOverSomeTimeMachineContainer (event) {
|
||||
if (event.containerId === undefined) {
|
||||
/* This happens when the mouse over was not at the instance of a certain scale, but anywhere else. */
|
||||
visible = true
|
||||
} else {
|
||||
if (event.containerId === thisObject.container.id) {
|
||||
visible = true
|
||||
} else {
|
||||
visible = false
|
||||
turnOnCounter = 0
|
||||
}
|
||||
}
|
||||
mouse = {
|
||||
position: {
|
||||
x: event.x,
|
||||
y: event.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
isMouseOver = true
|
||||
event.containerId = thisObject.container.id
|
||||
thisObject.container.eventHandler.raiseEvent('onMouseOverScale', event)
|
||||
}
|
||||
|
||||
function onMouseNotOver () {
|
||||
isMouseOver = false
|
||||
}
|
||||
|
||||
function physics () {
|
||||
readObjectState()
|
||||
positioningPhysics()
|
||||
}
|
||||
|
||||
function positioningPhysics () {
|
||||
/* Container Limits */
|
||||
|
||||
let upCorner = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let bottonCorner = {
|
||||
x: limitingContainer.frame.width,
|
||||
y: limitingContainer.frame.height
|
||||
}
|
||||
|
||||
upCorner = transformThisPoint(upCorner, limitingContainer)
|
||||
bottonCorner = transformThisPoint(bottonCorner, limitingContainer)
|
||||
|
||||
upCorner = limitingContainer.fitFunction(upCorner, true)
|
||||
bottonCorner = limitingContainer.fitFunction(bottonCorner, true)
|
||||
|
||||
/* We will check if we need to change the bottom because of being one of many scales of the same type */
|
||||
let displaceFactor = 0
|
||||
if (thisObject.payload.parentNode === undefined) { return } // This happens when in the process of deleting the scale, timeline chart or time machine.
|
||||
if (thisObject.payload.parentNode.type === 'Timeline Chart') {
|
||||
if (thisObject.payload.parentNode.payload.parentNode !== undefined) {
|
||||
if (thisObject.payload.parentNode.payload.parentNode.timeFrameScale !== undefined) {
|
||||
if (thisObject.payload.parentNode.payload.parentNode.timeFrameScale.payload.isVisible === true) {
|
||||
displaceFactor++
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < thisObject.payload.parentNode.payload.parentNode.timelineCharts.length; i++) {
|
||||
let timelineChart = thisObject.payload.parentNode.payload.parentNode.timelineCharts[i]
|
||||
if (timelineChart.timeFrameScale !== undefined) {
|
||||
if (thisObject.payload.node.id !== timelineChart.timeFrameScale.id) {
|
||||
if (timelineChart.timeFrameScale.payload.isVisible === true) {
|
||||
displaceFactor++
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bottonCorner.y = bottonCorner.y - thisObject.container.frame.height * displaceFactor
|
||||
|
||||
/* Positioning */
|
||||
timePoint = {
|
||||
x: 0,
|
||||
y: limitingContainer.frame.height
|
||||
}
|
||||
|
||||
timePoint = transformThisPoint(timePoint, limitingContainer.frame.container)
|
||||
timePoint.x = mouse.position.x - thisObject.container.frame.width / 2
|
||||
|
||||
/* Checking against the container limits. */
|
||||
if (timePoint.x < upCorner.x) { timePoint.x = upCorner.x }
|
||||
if (timePoint.x + thisObject.container.frame.width > bottonCorner.x) { timePoint.x = bottonCorner.x - thisObject.container.frame.width }
|
||||
if (timePoint.y < upCorner.y + thisObject.container.frame.height) { timePoint.y = upCorner.y + thisObject.container.frame.height }
|
||||
if (timePoint.y > bottonCorner.y) { timePoint.y = bottonCorner.y }
|
||||
|
||||
thisObject.container.frame.position.x = timePoint.x
|
||||
thisObject.container.frame.position.y = timePoint.y - thisObject.container.frame.height
|
||||
|
||||
thisObject.isVisible = true
|
||||
thisObject.payload.isVisible = true
|
||||
if (thisObject.container.frame.position.y + thisObject.container.frame.height > bottonCorner.y ||
|
||||
thisObject.container.frame.position.y - thisObject.container.frame.height * 3 < upCorner.y) {
|
||||
thisObject.isVisible = false
|
||||
thisObject.payload.isVisible = false
|
||||
}
|
||||
if (thisObject.layersOn === 0) {
|
||||
thisObject.isVisible = false
|
||||
thisObject.payload.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
function onViewportZoomChanged (event) {
|
||||
if (event !== undefined) { // it is undefined when the level is just being animated.
|
||||
if (event.shiftKey === false) { return } // with no shft key pressed, no automatic change in scale
|
||||
let currentTimeFrame = thisObject.timeFrame
|
||||
let timeFrame = recalculatePeriod(event.newLevel)
|
||||
if (timeFrame !== currentTimeFrame) {
|
||||
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 (timeFrame === record[0]) {
|
||||
filePeriodIndex = i
|
||||
timeFrameIndex = j
|
||||
}
|
||||
}
|
||||
}
|
||||
newTimeFrame()
|
||||
saveObjectState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
delta = event.wheelDelta
|
||||
if (delta < 0) {
|
||||
timeFrameIndex--
|
||||
if (timeFrameIndex < 0) {
|
||||
filePeriodIndex--
|
||||
if (filePeriodIndex < 0) {
|
||||
filePeriodIndex = 0
|
||||
timeFrameIndex = 0
|
||||
} else {
|
||||
timeFrameIndex = timeFramesMasterArray[filePeriodIndex].length - 1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
timeFrameIndex++
|
||||
if (timeFrameIndex > timeFramesMasterArray[filePeriodIndex].length - 1) {
|
||||
filePeriodIndex++
|
||||
if (filePeriodIndex > timeFramesMasterArray.length - 1) {
|
||||
filePeriodIndex = timeFramesMasterArray.length - 1
|
||||
timeFrameIndex = timeFramesMasterArray[filePeriodIndex].length - 1
|
||||
} else {
|
||||
timeFrameIndex = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newTimeFrame()
|
||||
saveObjectState()
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
}
|
||||
}
|
||||
|
||||
function saveObjectState () {
|
||||
try {
|
||||
let code = JSON.parse(thisObject.payload.node.code)
|
||||
code.value = timeFrameLabel
|
||||
thisObject.payload.node.code = JSON.stringify(code)
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
}
|
||||
|
||||
function readObjectState () {
|
||||
try {
|
||||
let code = JSON.parse(thisObject.payload.node.code)
|
||||
if (code.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]) {
|
||||
filePeriodIndex = i
|
||||
timeFrameIndex = j
|
||||
found = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found === true) {
|
||||
newTimeFrame()
|
||||
} else {
|
||||
saveObjectState()
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
}
|
||||
|
||||
function newTimeFrame () {
|
||||
let timeFrameArray = timeFramesMasterArray[filePeriodIndex]
|
||||
thisObject.timeFrame = timeFrameArray[timeFrameIndex][0]
|
||||
timeFrameLabel = timeFrameArray[timeFrameIndex][1]
|
||||
// console.log('NEW TIME FRAME LABEL', timeFrameLabel)
|
||||
let event = {}
|
||||
event.timeFrame = thisObject.timeFrame
|
||||
thisObject.container.eventHandler.raiseEvent('Time Frame Value Changed', event)
|
||||
}
|
||||
|
||||
function draw () {
|
||||
drawScaleBox()
|
||||
if (visible === false) {
|
||||
drawScaleDisplayCover(thisObject.container)
|
||||
}
|
||||
}
|
||||
|
||||
function drawForeground () {
|
||||
if (isMouseOver === true) {
|
||||
drawScaleBox()
|
||||
}
|
||||
}
|
||||
|
||||
function drawScaleBox () {
|
||||
if (timeFrameLabel === undefined) { return }
|
||||
|
||||
let label = timeFrameLabel.split('-')
|
||||
let label1 = thisObject.payload.node.payload.parentNode.name
|
||||
let label2 = label[0]
|
||||
let label3 = label[1].toUpperCase()
|
||||
|
||||
let icon1 = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.type)
|
||||
let icon2 = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
|
||||
drawScaleDisplay(label1, label2, label3, 0, 0, 0, icon1, icon2, thisObject.container, backgroundColor)
|
||||
}
|
||||
}
|
||||
@@ -1,324 +0,0 @@
|
||||
function newTimePeriodScale () {
|
||||
const MODULE_NAME = 'Time Period Scale'
|
||||
|
||||
let thisObject = {
|
||||
timePeriod: undefined,
|
||||
container: undefined,
|
||||
draw: draw,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
const FILES_PERIOD_DEFAULT_VALUE = 0
|
||||
const TIME_PERIOD_DEFAULT_VALUE = 0
|
||||
const MIN_HEIGHT = 50
|
||||
|
||||
let mouse = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
|
||||
let visible = true
|
||||
let timeLineCoordinateSystem
|
||||
let objectStorage = {}
|
||||
let filePeriodIndex = FILES_PERIOD_DEFAULT_VALUE
|
||||
let timePeriodIndex = TIME_PERIOD_DEFAULT_VALUE
|
||||
let timePeriodsMasterArray = [marketFilesPeriods, dailyFilePeriods]
|
||||
let timePeriodLabel = ''
|
||||
|
||||
let onMouseWheelEventSubscriptionId
|
||||
let onMouseOverEventSubscriptionId
|
||||
let onMouseNotOverEventSubscriptionId
|
||||
let onZoomChangedEventSubscriptionId
|
||||
|
||||
setupContainer()
|
||||
return thisObject
|
||||
|
||||
function setupContainer () {
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME)
|
||||
|
||||
thisObject.container.isDraggeable = false
|
||||
thisObject.container.isClickeable = false
|
||||
thisObject.container.isWheelable = true
|
||||
}
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseWheelEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onZoomChangedEventSubscriptionId)
|
||||
|
||||
timeLineCoordinateSystem = undefined
|
||||
objectStorage = undefined
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
setupContainer()
|
||||
}
|
||||
|
||||
function initialize (pTimeLineCoordinateSystem) {
|
||||
timeLineCoordinateSystem = pTimeLineCoordinateSystem
|
||||
|
||||
onMouseWheelEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
|
||||
readObjectState()
|
||||
newTimePeriod()
|
||||
|
||||
onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', function (event) {
|
||||
mouse.position.x = event.x
|
||||
mouse.position.y = event.y
|
||||
|
||||
visible = true
|
||||
})
|
||||
|
||||
onMouseWheelEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', function (event) {
|
||||
visible = false
|
||||
})
|
||||
|
||||
onZoomChangedEventSubscriptionId = viewPort.eventHandler.listenToEvent('Zoom Changed', onZoomChanged)
|
||||
}
|
||||
|
||||
function onZoomChanged (event) {
|
||||
if (event !== undefined) { // it is undefined when the level is just being animated.
|
||||
let currentTimePeriod = thisObject.timePeriod
|
||||
let timePeriod = recalculatePeriod(event.newLevel)
|
||||
if (timePeriod !== currentTimePeriod) {
|
||||
for (let i = 0; i < timePeriodsMasterArray.length; i++) {
|
||||
let timePeriodArray = timePeriodsMasterArray[i]
|
||||
for (let j = 0; j < timePeriodArray.length; j++) {
|
||||
let record = timePeriodArray[j]
|
||||
if (timePeriod === record[0]) {
|
||||
filePeriodIndex = i
|
||||
timePeriodIndex = j
|
||||
}
|
||||
}
|
||||
}
|
||||
saveObjectState()
|
||||
newTimePeriod()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
delta = event.wheelDelta
|
||||
if (delta < 0) {
|
||||
timePeriodIndex--
|
||||
if (timePeriodIndex < 0) {
|
||||
filePeriodIndex--
|
||||
if (filePeriodIndex < 0) {
|
||||
filePeriodIndex = 0
|
||||
timePeriodIndex = 0
|
||||
} else {
|
||||
timePeriodIndex = timePeriodsMasterArray[filePeriodIndex].length - 1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
timePeriodIndex++
|
||||
if (timePeriodIndex > timePeriodsMasterArray[filePeriodIndex].length - 1) {
|
||||
filePeriodIndex++
|
||||
if (filePeriodIndex > timePeriodsMasterArray.length - 1) {
|
||||
filePeriodIndex = timePeriodsMasterArray.length - 1
|
||||
timePeriodIndex = timePeriodsMasterArray[filePeriodIndex].length - 1
|
||||
} else {
|
||||
timePeriodIndex = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saveObjectState()
|
||||
newTimePeriod()
|
||||
}
|
||||
|
||||
function getContainer (pPoint) {
|
||||
let container
|
||||
|
||||
/* In this case we manually frame this point since we do a very special treatment of the position of this scale. */
|
||||
let point = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
point.x = pPoint.x - thisObject.container.frame.position.x
|
||||
point.y = pPoint.y - thisObject.container.frame.position.y
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, undefined, true) === true) {
|
||||
return thisObject.container
|
||||
} else {
|
||||
/* This point does not belong to this space. */
|
||||
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
function saveObjectState () {
|
||||
objectStorage.filePeriodIndex = filePeriodIndex
|
||||
objectStorage.timePeriodIndex = timePeriodIndex
|
||||
window.localStorage.setItem(MODULE_NAME, JSON.stringify(objectStorage))
|
||||
}
|
||||
|
||||
function readObjectState () {
|
||||
let objectStorageString = window.localStorage.getItem(MODULE_NAME)
|
||||
if (objectStorageString !== null && objectStorageString !== '') {
|
||||
objectStorage = JSON.parse(objectStorageString)
|
||||
filePeriodIndex = objectStorage.filePeriodIndex
|
||||
timePeriodIndex = objectStorage.timePeriodIndex
|
||||
}
|
||||
}
|
||||
|
||||
function newTimePeriod () {
|
||||
let timePeriodArray = timePeriodsMasterArray[filePeriodIndex]
|
||||
thisObject.timePeriod = timePeriodArray[timePeriodIndex][0]
|
||||
timePeriodLabel = timePeriodArray[timePeriodIndex][1]
|
||||
|
||||
let event = {}
|
||||
event.timePeriod = thisObject.timePeriod
|
||||
thisObject.container.eventHandler.raiseEvent('Time Period Changed', event)
|
||||
window.localStorage.setItem('Current Time Period', JSON.stringify({filePeriodIndex: filePeriodIndex, timePeriodIndex: timePeriodIndex}))
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (visible === false) { return }
|
||||
|
||||
/* We need this scale to match the shape of its parent when the parent is inside the viewPort, when it is not, we need the scale still
|
||||
to be visible at the top of the viewPort. */
|
||||
|
||||
let frame = thisObject.container.parentContainer.frame
|
||||
let point1
|
||||
let point2
|
||||
let point3
|
||||
let point4
|
||||
|
||||
point1 = {
|
||||
x: 0,
|
||||
y: frame.height - frame.height * 2 / 100
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: frame.width,
|
||||
y: frame.height - frame.height * 2 / 100
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: frame.width,
|
||||
y: frame.height
|
||||
}
|
||||
|
||||
point4 = {
|
||||
x: 0,
|
||||
y: frame.height
|
||||
}
|
||||
|
||||
point5 = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
/* Now the transformations. */
|
||||
|
||||
point1 = transformThisPoint(point1, frame.container)
|
||||
point2 = transformThisPoint(point2, frame.container)
|
||||
point3 = transformThisPoint(point3, frame.container)
|
||||
point4 = transformThisPoint(point4, frame.container)
|
||||
point5 = transformThisPoint(point5, frame.container)
|
||||
|
||||
point1 = viewPort.fitIntoVisibleArea(point1)
|
||||
point2 = viewPort.fitIntoVisibleArea(point2)
|
||||
point3 = viewPort.fitIntoVisibleArea(point3)
|
||||
point4 = viewPort.fitIntoVisibleArea(point4)
|
||||
point5 = viewPort.fitIntoVisibleArea(point5)
|
||||
|
||||
if (point3.y - point2.y < MIN_HEIGHT) {
|
||||
point1.y = point3.y - MIN_HEIGHT
|
||||
point2.y = point3.y - MIN_HEIGHT
|
||||
}
|
||||
|
||||
/* Lets start the drawing. */
|
||||
|
||||
let displacement = viewPort.margins.BOTTOM - COCKPIT_SPACE_HEIGHT
|
||||
|
||||
/*
|
||||
browserCanvasContext.beginPath()
|
||||
browserCanvasContext.moveTo(point1.x, point1.y + displacement)
|
||||
browserCanvasContext.lineTo(point2.x, point2.y + displacement)
|
||||
browserCanvasContext.lineTo(point3.x, point3.y + displacement)
|
||||
browserCanvasContext.lineTo(point4.x, point4.y + displacement)
|
||||
browserCanvasContext.lineTo(point1.x, point1.y + displacement)
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
browserCanvasContext.strokeStyle = 'rgba(150, 150, 150, 1)'
|
||||
browserCanvasContext.lineWidth = 1
|
||||
browserCanvasContext.stroke()
|
||||
*/
|
||||
|
||||
thisObject.container.frame.position.x = point1.x
|
||||
thisObject.container.frame.position.y = point1.y + displacement
|
||||
|
||||
thisObject.container.frame.width = point2.x - point1.x
|
||||
thisObject.container.frame.height = point3.y - point2.y
|
||||
|
||||
/* Common Variables */
|
||||
|
||||
let label = timePeriodLabel.split('-')
|
||||
let label1 = label[0]
|
||||
let label2 = label[1].toUpperCase()
|
||||
let fontSize1 = 20
|
||||
let fontSize2 = 10
|
||||
|
||||
const RED_LINE_HIGHT = 5
|
||||
const OPACITY = 1
|
||||
|
||||
let centerPoint = {
|
||||
x: mouse.position.x,
|
||||
y: point1.y + viewPort.margins.BOTTOM
|
||||
}
|
||||
|
||||
let container = newContainer()
|
||||
container.initialize('Visible Time Scale')
|
||||
container.frame.width = 60
|
||||
container.frame.height = 25
|
||||
container.frame.position.x = centerPoint.x - container.frame.width / 2
|
||||
container.frame.position.y = centerPoint.y - container.frame.height / 2
|
||||
|
||||
let params = {
|
||||
cornerRadius: 3,
|
||||
lineWidth: RED_LINE_HIGHT,
|
||||
container: container,
|
||||
borderColor: UI_COLOR.RUSTED_RED,
|
||||
castShadow: false,
|
||||
backgroundColor: UI_COLOR.DARK,
|
||||
opacity: OPACITY
|
||||
}
|
||||
|
||||
roundedCornersBackground(params)
|
||||
|
||||
/* Place the Text */
|
||||
|
||||
let xOffset1 = label1.length * fontSize1 * FONT_ASPECT_RATIO
|
||||
|
||||
let labelPoint1 = {
|
||||
x: mouse.position.x - xOffset1 / 2 - 14,
|
||||
y: point1.y + viewPort.margins.BOTTOM + 6
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize1 + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
|
||||
browserCanvasContext.fillText(label1, labelPoint1.x, labelPoint1.y)
|
||||
|
||||
let xOffset2 = label2.length * fontSize2 * FONT_ASPECT_RATIO
|
||||
|
||||
let labelPoint2 = {
|
||||
x: mouse.position.x - xOffset2 / 2 - 3 + 14,
|
||||
y: point1.y + viewPort.margins.BOTTOM + 6
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize2 + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
|
||||
browserCanvasContext.fillText(label2, labelPoint2.x, labelPoint2.y)
|
||||
}
|
||||
}
|
||||
+255
-52
@@ -2,21 +2,28 @@ function newTimeScale () {
|
||||
const MODULE_NAME = 'Time Scale'
|
||||
|
||||
let thisObject = {
|
||||
lenghtPercentage: undefined,
|
||||
scale: undefined,
|
||||
container: undefined,
|
||||
date: undefined,
|
||||
fitFunction: undefined,
|
||||
visible: true,
|
||||
payload: undefined,
|
||||
isVisible: true,
|
||||
fromDate: undefined,
|
||||
toDate: undefined,
|
||||
onMouseOverSomeTimeMachineContainer: onMouseOverSomeTimeMachineContainer,
|
||||
physics: physics,
|
||||
draw: draw,
|
||||
drawForeground: drawForeground,
|
||||
getContainer: getContainer,
|
||||
initialize: initialize,
|
||||
finalize: finalize
|
||||
}
|
||||
|
||||
const LENGHT_PERCENTAGE_DEFAULT_VALUE = 5
|
||||
const STEP_SIZE = 5
|
||||
const MIN_HEIGHT = 50
|
||||
const DEFAULT_SCALE = 0
|
||||
const STEP_SCALE = 2.5
|
||||
const MIN_SCALE = 0
|
||||
const MAX_SCALE = 250
|
||||
const SNAP_THRESHOLD_SCALE = 0
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME)
|
||||
@@ -26,57 +33,120 @@ function newTimeScale () {
|
||||
thisObject.container.isWheelable = true
|
||||
thisObject.container.detectMouseOver = true
|
||||
|
||||
thisObject.container.frame.width = 190
|
||||
thisObject.container.frame.height = 25
|
||||
thisObject.container.frame.width = UI_PANEL.WIDTH.NORMAL
|
||||
thisObject.container.frame.height = 40
|
||||
|
||||
let visible = true
|
||||
let isMouseOver
|
||||
|
||||
let onMouseWheelEventSubscriptionId
|
||||
let onMouseOverEventSubscriptionId
|
||||
let onMouseNotOverEventSubscriptionId
|
||||
|
||||
let coordinateSystem
|
||||
let limitingContainer
|
||||
|
||||
let mouse = {
|
||||
position: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
let scaleTimer = 0
|
||||
return thisObject
|
||||
|
||||
function finalize () {
|
||||
thisObject.container.eventHandler.stopListening(onMouseWheelEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseOverEventSubscriptionId)
|
||||
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSubscriptionId)
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
thisObject.fitFunction = undefined
|
||||
thisObject.payload = undefined
|
||||
|
||||
coordinateSystem = undefined
|
||||
limitingContainer = undefined
|
||||
mouse = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
function initialize (pCoordinateSystem, pLimitingContainer) {
|
||||
coordinateSystem = pCoordinateSystem
|
||||
limitingContainer = pLimitingContainer
|
||||
|
||||
thisObject.lenghtPercentage = window.localStorage.getItem(MODULE_NAME)
|
||||
if (!thisObject.lenghtPercentage) {
|
||||
thisObject.lenghtPercentage = LENGHT_PERCENTAGE_DEFAULT_VALUE
|
||||
} else {
|
||||
thisObject.lenghtPercentage = JSON.parse(thisObject.lenghtPercentage)
|
||||
}
|
||||
thisObject.fromDate = coordinateSystem.min.x
|
||||
thisObject.toDate = coordinateSystem.max.x
|
||||
|
||||
onMouseWheelEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
onMouseOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
|
||||
onMouseNotOverEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
|
||||
|
||||
thisObject.scale = DEFAULT_SCALE
|
||||
readObjectState()
|
||||
|
||||
let event = {}
|
||||
event.lenghtPercentage = thisObject.lenghtPercentage
|
||||
thisObject.container.eventHandler.raiseEvent('Lenght Percentage Changed', event)
|
||||
event.scale = thisObject.scale
|
||||
thisObject.container.eventHandler.raiseEvent('Time Scale Value Changed', event)
|
||||
}
|
||||
|
||||
function onMouseOver () {
|
||||
function onMouseOverSomeTimeMachineContainer (event) {
|
||||
if (event.containerId === undefined) {
|
||||
/* This happens when the mouse over was not at the instance of a certain scale, but anywhere else. */
|
||||
visible = true
|
||||
} else {
|
||||
if (event.containerId === thisObject.container.id) {
|
||||
visible = true
|
||||
} else {
|
||||
visible = false
|
||||
turnOnCounter = 0
|
||||
}
|
||||
}
|
||||
mouse = {
|
||||
position: {
|
||||
x: event.x,
|
||||
y: event.y
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseOver (event) {
|
||||
isMouseOver = true
|
||||
event.containerId = thisObject.container.id
|
||||
thisObject.container.eventHandler.raiseEvent('onMouseOverScale', event)
|
||||
}
|
||||
|
||||
function onMouseNotOver () {
|
||||
isMouseOver = false
|
||||
scaleTimer = 0
|
||||
}
|
||||
|
||||
function onMouseWheel (event) {
|
||||
let morePower = 1
|
||||
if (event.buttons === 4) { morePower = 5 } // Mouse wheel pressed.
|
||||
|
||||
delta = event.wheelDelta
|
||||
if (delta < 0) {
|
||||
thisObject.lenghtPercentage = thisObject.lenghtPercentage - STEP_SIZE
|
||||
if (thisObject.lenghtPercentage < STEP_SIZE) { thisObject.lenghtPercentage = STEP_SIZE }
|
||||
thisObject.scale = thisObject.scale - STEP_SCALE * morePower
|
||||
if (thisObject.scale < MIN_SCALE) { thisObject.scale = MIN_SCALE }
|
||||
} else {
|
||||
thisObject.lenghtPercentage = thisObject.lenghtPercentage + STEP_SIZE
|
||||
if (thisObject.lenghtPercentage > 400) { thisObject.lenghtPercentage = 400 }
|
||||
thisObject.scale = thisObject.scale + STEP_SCALE * morePower
|
||||
if (thisObject.scale > MAX_SCALE) { thisObject.scale = MAX_SCALE }
|
||||
}
|
||||
|
||||
event.lenghtPercentage = thisObject.lenghtPercentage
|
||||
thisObject.container.eventHandler.raiseEvent('Lenght Percentage Changed', event)
|
||||
if (
|
||||
thisObject.scale <= DEFAULT_SCALE + SNAP_THRESHOLD_SCALE &&
|
||||
thisObject.scale >= DEFAULT_SCALE - SNAP_THRESHOLD_SCALE
|
||||
) {
|
||||
event.scale = DEFAULT_SCALE
|
||||
} else {
|
||||
event.scale = thisObject.scale
|
||||
}
|
||||
|
||||
window.localStorage.setItem(MODULE_NAME, thisObject.lenghtPercentage)
|
||||
event.isUserAction = true
|
||||
thisObject.container.eventHandler.raiseEvent('Time Scale Value Changed', event)
|
||||
|
||||
saveObjectState()
|
||||
scaleTimer = 100
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
@@ -85,18 +155,163 @@ function newTimeScale () {
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
function saveObjectState () {
|
||||
try {
|
||||
let code = JSON.parse(thisObject.payload.node.code)
|
||||
code.scale = thisObject.scale / MAX_SCALE * 100
|
||||
code.scale = code.scale.toFixed(0)
|
||||
code.fromDate = (new Date(thisObject.fromDate)).toISOString()
|
||||
code.toDate = (new Date(thisObject.toDate)).toISOString()
|
||||
thisObject.payload.node.code = JSON.stringify(code, null, 4)
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
}
|
||||
|
||||
function readObjectState () {
|
||||
try {
|
||||
let code = JSON.parse(thisObject.payload.node.code)
|
||||
|
||||
if (isNaN(code.scale) || code.scale === null || code.scale === undefined) {
|
||||
// not using this value
|
||||
} else {
|
||||
code.scale = code.scale / 100 * MAX_SCALE
|
||||
if (code.scale < MIN_SCALE) { code.scale = MIN_SCALE }
|
||||
if (code.scale > MAX_SCALE) { code.scale = MAX_SCALE }
|
||||
|
||||
if (code.scale !== thisObject.scale) {
|
||||
thisObject.scale = code.scale
|
||||
let event = {}
|
||||
if (
|
||||
thisObject.scale <= DEFAULT_SCALE + SNAP_THRESHOLD_SCALE &&
|
||||
thisObject.scale >= DEFAULT_SCALE - SNAP_THRESHOLD_SCALE
|
||||
) {
|
||||
event.scale = DEFAULT_SCALE
|
||||
} else {
|
||||
event.scale = thisObject.scale
|
||||
}
|
||||
thisObject.container.eventHandler.raiseEvent('Time Scale Value Changed', event)
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(isNaN(Date.parse(code.fromDate)) || code.fromDate === null || code.fromDate === undefined) ||
|
||||
(isNaN(Date.parse(code.toDate)) || code.toDate === null || code.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)
|
||||
coordinateSystem.min.x = thisObject.fromDate
|
||||
coordinateSystem.max.x = thisObject.toDate
|
||||
coordinateSystem.recalculateScale()
|
||||
}
|
||||
}
|
||||
saveObjectState() // this overrides any invalid value at the config.
|
||||
} catch (err) {
|
||||
// we ignore errors here since most likely they will be parsing errors.
|
||||
}
|
||||
}
|
||||
|
||||
function physics () {
|
||||
scaleTimer--
|
||||
readObjectState()
|
||||
positioningPhysics()
|
||||
}
|
||||
|
||||
function positioningPhysics () {
|
||||
/* Container Limits */
|
||||
|
||||
let upCorner = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let bottonCorner = {
|
||||
x: limitingContainer.frame.width,
|
||||
y: limitingContainer.frame.height
|
||||
}
|
||||
|
||||
upCorner = transformThisPoint(upCorner, limitingContainer)
|
||||
bottonCorner = transformThisPoint(bottonCorner, limitingContainer)
|
||||
|
||||
upCorner = limitingContainer.fitFunction(upCorner, true)
|
||||
bottonCorner = limitingContainer.fitFunction(bottonCorner, true)
|
||||
|
||||
/* Mouse Position Date Calculation */
|
||||
let timePoint = {
|
||||
x: mouse.position.x,
|
||||
y: 0
|
||||
}
|
||||
|
||||
let mouseDate = getDateFromPoint(timePoint, limitingContainer, coordinateSystem)
|
||||
|
||||
thisObject.date = new Date(mouseDate)
|
||||
|
||||
/* timeScale Positioning */
|
||||
timePoint = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
timePoint = transformThisPoint(timePoint, limitingContainer.frame.container)
|
||||
timePoint.x = mouse.position.x - thisObject.container.frame.width / 2
|
||||
|
||||
/* Checking against the container limits. */
|
||||
if (timePoint.x < upCorner.x) { timePoint.x = upCorner.x }
|
||||
if (timePoint.x + thisObject.container.frame.width > bottonCorner.x) { timePoint.x = bottonCorner.x - thisObject.container.frame.width }
|
||||
if (timePoint.y < upCorner.y) { timePoint.y = upCorner.y }
|
||||
if (timePoint.y + thisObject.container.frame.height > bottonCorner.y) { timePoint.y = bottonCorner.y - thisObject.container.frame.height }
|
||||
|
||||
thisObject.container.frame.position.x = timePoint.x
|
||||
thisObject.container.frame.position.y = timePoint.y
|
||||
|
||||
thisObject.isVisible = true
|
||||
if (thisObject.container.frame.position.y + thisObject.container.frame.height * 4 > bottonCorner.y ||
|
||||
thisObject.container.frame.position.y < upCorner.y) {
|
||||
thisObject.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
drawTime()
|
||||
drawArrows()
|
||||
drawScaleBox()
|
||||
if (visible === false) {
|
||||
drawScaleDisplayCover(thisObject.container)
|
||||
}
|
||||
}
|
||||
|
||||
function drawForeground () {
|
||||
if (isMouseOver === true) {
|
||||
drawScaleBox()
|
||||
drawArrows()
|
||||
}
|
||||
}
|
||||
|
||||
function drawScaleBox () {
|
||||
if (thisObject.date === undefined) { return }
|
||||
|
||||
let label = thisObject.date.toUTCString()
|
||||
let labelArray = label.split(' ')
|
||||
let label1 = thisObject.payload.node.payload.parentNode.name
|
||||
let label2 = labelArray[1] + ' ' + labelArray[2] + ' ' + labelArray[3]
|
||||
let label3 = labelArray[4]
|
||||
|
||||
let icon1 = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.payload.parentNode.type)
|
||||
let icon2 = canvas.designerSpace.iconByUiObjectType.get(thisObject.payload.node.type)
|
||||
|
||||
let backgroundColor = UI_COLOR.BLACK
|
||||
|
||||
if (scaleTimer > 0) {
|
||||
label2 = (thisObject.scale / MAX_SCALE * 100).toFixed(0)
|
||||
label3 = 'SCALE'
|
||||
}
|
||||
|
||||
drawScaleDisplay(label1, label2, label3, 0, 0, 0, icon1, icon2, thisObject.container, backgroundColor)
|
||||
}
|
||||
|
||||
function drawArrows () {
|
||||
if (isMouseOver !== true) { return }
|
||||
if (thisObject.visible === false || thisObject.date === undefined) { return }
|
||||
if (visible === false || thisObject.date === undefined) { return }
|
||||
|
||||
const X_OFFSET = thisObject.container.frame.width / 2
|
||||
const Y_OFFSET = thisObject.container.frame.height / 2 - 10
|
||||
@@ -106,8 +321,8 @@ function newTimeScale () {
|
||||
const OPACITY = 0.2
|
||||
const DISTANCE_BETWEEN_ARROWS = 10
|
||||
const MIN_DISTANCE_FROM_CENTER = 110
|
||||
const CURRENT_VALUE_DISTANCE = MIN_DISTANCE_FROM_CENTER + thisObject.lenghtPercentage
|
||||
const MAX_DISTANCE_FROM_CENTER = MIN_DISTANCE_FROM_CENTER + 400 + DISTANCE_BETWEEN_ARROWS
|
||||
const CURRENT_SCALE_DISTANCE = MIN_DISTANCE_FROM_CENTER + thisObject.scale
|
||||
const MAX_DISTANCE_FROM_CENTER = MIN_DISTANCE_FROM_CENTER + MAX_SCALE + DISTANCE_BETWEEN_ARROWS
|
||||
|
||||
let ARROW_DIRECTION = 0
|
||||
|
||||
@@ -118,17 +333,17 @@ function newTimeScale () {
|
||||
|
||||
function drawTwoArrows () {
|
||||
point1 = {
|
||||
x: X_OFFSET - WIDTH / 2 * ARROW_DIRECTION + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION,
|
||||
x: X_OFFSET - WIDTH / 2 * ARROW_DIRECTION + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION,
|
||||
y: Y_OFFSET - 0
|
||||
}
|
||||
|
||||
point2 = {
|
||||
x: X_OFFSET + WIDTH / 2 * ARROW_DIRECTION + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION,
|
||||
x: X_OFFSET + WIDTH / 2 * ARROW_DIRECTION + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION,
|
||||
y: Y_OFFSET + HEIGHT / 2
|
||||
}
|
||||
|
||||
point3 = {
|
||||
x: X_OFFSET - WIDTH / 2 * ARROW_DIRECTION + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION,
|
||||
x: X_OFFSET - WIDTH / 2 * ARROW_DIRECTION + DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION,
|
||||
y: Y_OFFSET + HEIGHT
|
||||
}
|
||||
|
||||
@@ -137,17 +352,17 @@ function newTimeScale () {
|
||||
point3 = thisObject.container.frame.frameThisPoint(point3)
|
||||
|
||||
point4 = {
|
||||
x: X_OFFSET - WIDTH / 2 * ARROW_DIRECTION - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION,
|
||||
x: X_OFFSET - WIDTH / 2 * ARROW_DIRECTION - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION,
|
||||
y: Y_OFFSET - 0
|
||||
}
|
||||
|
||||
point5 = {
|
||||
x: X_OFFSET + WIDTH / 2 * ARROW_DIRECTION - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION,
|
||||
x: X_OFFSET + WIDTH / 2 * ARROW_DIRECTION - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION,
|
||||
y: Y_OFFSET + HEIGHT / 2
|
||||
}
|
||||
|
||||
point6 = {
|
||||
x: X_OFFSET - WIDTH / 2 * ARROW_DIRECTION - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_VALUE_DISTANCE * ARROW_DIRECTION,
|
||||
x: X_OFFSET - WIDTH / 2 * ARROW_DIRECTION - DISTANCE_BETWEEN_ARROWS / 2 * ARROW_DIRECTION + CURRENT_SCALE_DISTANCE * ARROW_DIRECTION,
|
||||
y: Y_OFFSET + HEIGHT
|
||||
}
|
||||
|
||||
@@ -195,16 +410,4 @@ function newTimeScale () {
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
function drawTime () {
|
||||
if (thisObject.visible === false || thisObject.date === undefined) { return }
|
||||
|
||||
let label = thisObject.date.toUTCString()
|
||||
let labelArray = label.split(' ')
|
||||
let label1 = labelArray[1] + ' ' + labelArray[2] + ' ' + labelArray[3]
|
||||
let label2 = labelArray[4]
|
||||
|
||||
drawScaleDisplay(label1, label2, 10, 60, thisObject.container, thisObject.fitFunction)
|
||||
}
|
||||
}
|
||||
|
||||
+187
-61
@@ -13,17 +13,20 @@ function newChartSpace () {
|
||||
logger.fileName = MODULE_NAME
|
||||
|
||||
let thisObject = {
|
||||
visible: true,
|
||||
visible: undefined,
|
||||
container: undefined,
|
||||
timeMachines: [],
|
||||
inViewport: undefined,
|
||||
timeMachines: undefined,
|
||||
viewport: undefined,
|
||||
payload: undefined,
|
||||
reset: reset,
|
||||
oneScreenUp: oneScreenUp,
|
||||
oneScreenDown: oneScreenDown,
|
||||
oneScreenLeft: oneScreenLeft,
|
||||
oneScreenRight: oneScreenRight,
|
||||
fitIntoVisibleArea: fitIntoVisibleArea,
|
||||
fitFunction: fitFunction,
|
||||
isThisPointVisible: isThisPointVisible,
|
||||
physics: physics,
|
||||
drawBackground: drawBackground,
|
||||
draw: draw,
|
||||
getContainer: getContainer, // returns the inner most container that holds the point received by parameter.
|
||||
initialize: initialize,
|
||||
@@ -31,13 +34,27 @@ function newChartSpace () {
|
||||
}
|
||||
|
||||
let canvasBrowserResizedEventSubscriptionId
|
||||
let timeMachinesMap
|
||||
let syncWithDesignerLoop
|
||||
|
||||
const PERCENTAGE_OF_SCREEN_FOR_DISPLACEMENT = 25
|
||||
|
||||
setupContainer()
|
||||
initialSetup()
|
||||
return thisObject
|
||||
|
||||
function setupContainer () {
|
||||
function reset () {
|
||||
finalize()
|
||||
initialSetup()
|
||||
initialize()
|
||||
}
|
||||
|
||||
function initialSetup () {
|
||||
thisObject.timeMachines = []
|
||||
thisObject.visible = true
|
||||
timeMachinesMap = new Map()
|
||||
syncWithDesignerLoop = 0
|
||||
thisObject.inViewport = new Map()
|
||||
|
||||
thisObject.container = newContainer()
|
||||
thisObject.container.initialize(MODULE_NAME)
|
||||
|
||||
@@ -51,45 +68,46 @@ function newChartSpace () {
|
||||
timeMachine.finalize()
|
||||
}
|
||||
|
||||
thisObject.inViewport = undefined
|
||||
thisObject.timeMachines = undefined
|
||||
timeMachinesMap = undefined
|
||||
|
||||
thisObject.container.eventHandler.stopListening(canvasBrowserResizedEventSubscriptionId)
|
||||
|
||||
thisObject.container.finalize()
|
||||
thisObject.container = undefined
|
||||
setupContainer()
|
||||
|
||||
thisObject.viewport.finalize()
|
||||
thisObject.viewport = undefined
|
||||
|
||||
thisObject.payload = undefined
|
||||
}
|
||||
|
||||
function initialize () {
|
||||
let initializedCounter = 0
|
||||
let toInitialize = 1
|
||||
|
||||
canvasBrowserResizedEventSubscriptionId = window.canvasApp.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
|
||||
/* We create the first of many possible time machines that could live at the Chart Space. */
|
||||
|
||||
let timeMachine = newTimeMachine()
|
||||
|
||||
/* We make the time machine a little bit smaller than the current space. */
|
||||
|
||||
timeMachine.container.frame.position.x = thisObject.container.frame.width / 2 - timeMachine.container.frame.width / 2
|
||||
timeMachine.container.frame.position.y = thisObject.container.frame.height / 2 - timeMachine.container.frame.height / 2
|
||||
timeMachine.container.fitFunction = fitIntoVisibleArea
|
||||
timeMachine.fitFunction = fitIntoVisibleArea
|
||||
timeMachine.initialize(onTimeMachineInitialized)
|
||||
|
||||
function onTimeMachineInitialized (err) {
|
||||
initializedCounter++
|
||||
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] initialize -> Initialization Failed. -> Err ' + err.message) }
|
||||
return
|
||||
}
|
||||
|
||||
thisObject.timeMachines.push(timeMachine)
|
||||
|
||||
if (initializedCounter === toInitialize) {
|
||||
viewPort.raiseEvents() // These events will impacts on objects just initialized.
|
||||
let rootNodes = canvas.designerSpace.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 (thisObject.payload === undefined) {
|
||||
if (ERROR_LOG === true) { logger.write('[WARN] initialize -> There must exist a Charting Space at the Designer Space in order to enable Charts. PLease create one and refreash your browser. ') }
|
||||
return
|
||||
}
|
||||
|
||||
thisObject.viewport = newViewport()
|
||||
if (thisObject.payload.node.viewport === undefined) {
|
||||
if (ERROR_LOG === true) { logger.write('[WARN] initialize -> There must exist a Viewport node attached to the Charting Space node in order for the Viewport save its properties. ') }
|
||||
return
|
||||
} else {
|
||||
thisObject.viewport.payload = thisObject.payload.node.viewport.payload
|
||||
}
|
||||
|
||||
thisObject.viewport.initialize()
|
||||
|
||||
canvasBrowserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
}
|
||||
|
||||
function getContainer (point, purpose) {
|
||||
@@ -97,12 +115,25 @@ function newChartSpace () {
|
||||
|
||||
let container
|
||||
|
||||
/* Now we see which is the inner most container that has it */
|
||||
/* This first step is not actually to get the container but to allow things to be turned off in case there is a switch of focus from one time machine to another */
|
||||
for (let i = 0; i < thisObject.timeMachines.length; i++) {
|
||||
container = thisObject.timeMachines[i].container
|
||||
if (purpose === GET_CONTAINER_PURPOSE.MOUSE_OVER) {
|
||||
container.eventHandler.raiseEvent('onMouseNotOver')
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we see which is the inner most container that has it */
|
||||
for (let i = 0; i < thisObject.timeMachines.length; i++) {
|
||||
container = thisObject.timeMachines[i].getContainer(point, purpose)
|
||||
if (container !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
if (purpose !== undefined) {
|
||||
if (container.isForThisPurpose(purpose)) {
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return container
|
||||
}
|
||||
@@ -118,6 +149,7 @@ function newChartSpace () {
|
||||
}
|
||||
|
||||
function resize () {
|
||||
thisObject.viewport.resize()
|
||||
thisObject.container.frame.width = browserCanvas.width
|
||||
thisObject.container.frame.height = COCKPIT_SPACE_POSITION
|
||||
}
|
||||
@@ -125,10 +157,10 @@ function newChartSpace () {
|
||||
function oneScreenUp () {
|
||||
let displaceVector = {
|
||||
x: 0,
|
||||
y: +browserCanvas.height * PERCENTAGE_OF_SCREEN_FOR_DISPLACEMENT / 100
|
||||
y: browserCanvas.height * PERCENTAGE_OF_SCREEN_FOR_DISPLACEMENT / 100
|
||||
}
|
||||
|
||||
viewPort.displace(displaceVector)
|
||||
canvas.chartSpace.viewport.displace(displaceVector)
|
||||
}
|
||||
|
||||
function oneScreenDown () {
|
||||
@@ -137,7 +169,7 @@ function newChartSpace () {
|
||||
y: -browserCanvas.height * PERCENTAGE_OF_SCREEN_FOR_DISPLACEMENT / 100
|
||||
}
|
||||
|
||||
viewPort.displace(displaceVector)
|
||||
canvas.chartSpace.viewport.displace(displaceVector)
|
||||
}
|
||||
|
||||
function oneScreenLeft () {
|
||||
@@ -146,7 +178,7 @@ function newChartSpace () {
|
||||
y: 0
|
||||
}
|
||||
|
||||
viewPort.displace(displaceVector, true)
|
||||
canvas.chartSpace.viewport.displace(displaceVector, true)
|
||||
}
|
||||
|
||||
function oneScreenRight () {
|
||||
@@ -155,10 +187,10 @@ function newChartSpace () {
|
||||
y: 0
|
||||
}
|
||||
|
||||
viewPort.displace(displaceVector, true)
|
||||
canvas.chartSpace.viewport.displace(displaceVector, true)
|
||||
}
|
||||
|
||||
function fitIntoVisibleArea (point) {
|
||||
function fitFunction (point, fullVisible) {
|
||||
/* Here we check the boundaries of the resulting points, so they dont go out of the visible area. */
|
||||
|
||||
let returnPoint = {
|
||||
@@ -174,12 +206,18 @@ function newChartSpace () {
|
||||
returnPoint.x = 0
|
||||
}
|
||||
|
||||
if (point.y > COCKPIT_SPACE_POSITION + COCKPIT_SPACE_HEIGHT / 2) {
|
||||
returnPoint.y = COCKPIT_SPACE_POSITION + COCKPIT_SPACE_HEIGHT / 2
|
||||
if (fullVisible === true) {
|
||||
if (point.y > COCKPIT_SPACE_POSITION) {
|
||||
returnPoint.y = COCKPIT_SPACE_POSITION
|
||||
}
|
||||
} else {
|
||||
if (point.y > COCKPIT_SPACE_POSITION + COCKPIT_SPACE_HEIGHT / 2) {
|
||||
returnPoint.y = COCKPIT_SPACE_POSITION + COCKPIT_SPACE_HEIGHT / 2
|
||||
}
|
||||
}
|
||||
|
||||
if (point.y < 0) {
|
||||
returnPoint.y = 0
|
||||
if (point.y < TOP_SPACE_HEIGHT) {
|
||||
returnPoint.y = TOP_SPACE_HEIGHT
|
||||
}
|
||||
|
||||
return returnPoint
|
||||
@@ -206,8 +244,77 @@ function newChartSpace () {
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (thisObject.viewport !== undefined) {
|
||||
thisObject.viewport.physics()
|
||||
}
|
||||
|
||||
thisObjectPhysics()
|
||||
childrenPhysics()
|
||||
syncWithDesigner()
|
||||
}
|
||||
|
||||
function syncWithDesigner () {
|
||||
if (thisObject.payload === undefined) { return }
|
||||
if (thisObject.payload.node === undefined) { return }
|
||||
syncWithDesignerLoop = syncWithDesignerLoop + 0.00000000001
|
||||
|
||||
if (thisObject.payload.node.timeMachines !== undefined) {
|
||||
for (let j = 0; j < thisObject.payload.node.timeMachines.length; j++) {
|
||||
let node = thisObject.payload.node.timeMachines[j]
|
||||
let timeMachine = timeMachinesMap.get(node.id)
|
||||
if (timeMachine === undefined) {
|
||||
/* The time machine node is new, thus we need to initialize a new timeMachine */
|
||||
initializeTimeMachine(node, syncWithDesignerLoop)
|
||||
} else {
|
||||
/* The time machine already exists, we tag it as existing at the current loop. */
|
||||
timeMachine.syncWithDesignerLoop = syncWithDesignerLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We check all the timeMachines we have to see if we need to remove any of them */
|
||||
for (let i = 0; i < thisObject.timeMachines.length; i++) {
|
||||
let timeMachine = thisObject.timeMachines[i]
|
||||
if (timeMachine.syncWithDesignerLoop < syncWithDesignerLoop) {
|
||||
/* Must be removed */
|
||||
timeMachine.finalize()
|
||||
timeMachinesMap.delete(timeMachine.nodeId)
|
||||
thisObject.timeMachines.splice(i, 1)
|
||||
/* We remove one at the time */
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function initializeTimeMachine (node, syncWithDesignerLoop) {
|
||||
if (node.payload === undefined) { return } // not ready to consider this Time Machine
|
||||
if (node.payload.uiObject === undefined) { return }
|
||||
|
||||
let timeMachine = newTimeMachine()
|
||||
timeMachine.syncWithDesignerLoop = syncWithDesignerLoop
|
||||
timeMachine.payload = node.payload
|
||||
timeMachine.nodeId = node.id
|
||||
|
||||
timeMachinesMap.set(node.id, timeMachine)
|
||||
timeMachine.payload.uiObject.setValue('Loading...')
|
||||
|
||||
/* Setting up the new time machine. */
|
||||
timeMachine.container.frame.position.x = browserCanvas.width / 2 - TIME_MACHINE_WIDTH / 2
|
||||
timeMachine.container.frame.position.y = browserCanvas.height / 2 - TIME_MACHINE_HEIGHT / 2
|
||||
timeMachine.initialize(onTimeMachineInitialized)
|
||||
|
||||
function onTimeMachineInitialized (err) {
|
||||
if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
|
||||
if (ERROR_LOG === true) { logger.write('[ERROR] syncWithDesigner -> initializeTimeMachine -> Initialization Failed. -> Err ' + err.message) }
|
||||
return
|
||||
}
|
||||
|
||||
thisObject.timeMachines.push(timeMachine)
|
||||
timeMachine.payload.uiObject.setValue('')
|
||||
if (canvas.chartSpace.viewport !== undefined) {
|
||||
canvas.chartSpace.viewport.raiseEvents() // These events will impacts on objects just initialized.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function thisObjectPhysics () {
|
||||
@@ -219,27 +326,55 @@ function newChartSpace () {
|
||||
thisObject.visible = true
|
||||
}
|
||||
|
||||
viewPort.resize()
|
||||
if (canvas.chartSpace.viewport !== undefined) {
|
||||
canvas.chartSpace.viewport.resize()
|
||||
}
|
||||
}
|
||||
|
||||
function childrenPhysics () {
|
||||
for (let i = 0; i < thisObject.timeMachines.length; i++) {
|
||||
let timeMachine = thisObject.timeMachines[i]
|
||||
if (timeMachine.payload.node === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (timeMachine.container.frame.isInViewPort()) {
|
||||
thisObject.inViewport.set(timeMachine.payload.node.id, timeMachine)
|
||||
} else {
|
||||
thisObject.inViewport.delete(timeMachine.payload.node.id)
|
||||
}
|
||||
timeMachine.physics()
|
||||
}
|
||||
}
|
||||
|
||||
function drawBackground () {
|
||||
if (thisObject.visible !== true) { return }
|
||||
|
||||
drawSpaceBackground()
|
||||
|
||||
for (let i = 0; i < thisObject.timeMachines.length; i++) {
|
||||
let timeMachine = thisObject.timeMachines[i]
|
||||
let timeMachine = thisObject.timeMachines[thisObject.timeMachines.length - i - 1]
|
||||
timeMachine.drawBackground()
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (thisObject.visible !== true) { return }
|
||||
drawBackground()
|
||||
|
||||
for (let i = 0; i < thisObject.timeMachines.length; i++) {
|
||||
let timeMachine = thisObject.timeMachines[thisObject.timeMachines.length - i - 1]
|
||||
timeMachine.draw()
|
||||
}
|
||||
|
||||
drawForeground()
|
||||
}
|
||||
|
||||
function drawForeground () {
|
||||
for (let i = 0; i < thisObject.timeMachines.length; i++) {
|
||||
let timeMachine = thisObject.timeMachines[thisObject.timeMachines.length - i - 1]
|
||||
timeMachine.drawForeground()
|
||||
}
|
||||
}
|
||||
|
||||
function drawSpaceBackground () {
|
||||
let opacity = '1'
|
||||
let fromPoint = {
|
||||
@@ -258,13 +393,4 @@ function newChartSpace () {
|
||||
browserCanvasContext.closePath()
|
||||
browserCanvasContext.fill()
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (thisObject.visible !== true) { return }
|
||||
|
||||
for (let i = 0; i < thisObject.timeMachines.length; i++) {
|
||||
let timeMachine = thisObject.timeMachines[i]
|
||||
timeMachine.draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,10 +62,10 @@
|
||||
thisObject.container.frame.position.y = browserCanvas.height * INITIAL_POSITION / 100 - COCKPIT_SPACE_HEIGHT
|
||||
}
|
||||
|
||||
canvasBrowserResizedEventSubscriptionId = window.canvasApp.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
canvasBrowserResizedEventSubscriptionId = canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
selfMouseClickEventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick)
|
||||
|
||||
thisObject.assetBalances = newAssetBalances()
|
||||
thisObject.assetBalances = newQuotedAssetalances()
|
||||
thisObject.assetBalances.initialize()
|
||||
|
||||
thisObject.fullscreen = newFullScreen()
|
||||
@@ -150,14 +150,16 @@
|
||||
spacePosition: COCKPIT_SPACE_POSITION
|
||||
}
|
||||
window.localStorage.setItem(MODULE_NAME, JSON.stringify(storage))
|
||||
viewPort.resize()
|
||||
if (canvas.chartSpace.viewport !== undefined) {
|
||||
canvas.chartSpace.viewport.resize()
|
||||
}
|
||||
}
|
||||
|
||||
function getContainer (point) {
|
||||
let container
|
||||
|
||||
container = thisObject.fullscreen.getContainer(point)
|
||||
if (container !== undefined) { return container }
|
||||
// container = thisObject.fullscreen.getContainer(point)
|
||||
// if (container !== undefined) { return container }
|
||||
|
||||
if (thisObject.container.frame.isThisPointHere(point, true) === true) {
|
||||
return thisObject.container
|
||||
@@ -172,7 +174,7 @@
|
||||
drawBackground()
|
||||
|
||||
thisObject.assetBalances.draw()
|
||||
thisObject.fullscreen.draw()
|
||||
// thisObject.fullscreen.draw()
|
||||
}
|
||||
|
||||
function drawBackground () {
|
||||
@@ -183,7 +185,7 @@
|
||||
y: 0
|
||||
}
|
||||
|
||||
const RED_LINE_HIGHT = 5
|
||||
const RED_LINE_HIGHT = 2
|
||||
|
||||
zeroPoint = thisObject.container.frame.frameThisPoint(zeroPoint)
|
||||
|
||||
|
||||
+78
-11
@@ -35,14 +35,6 @@ function newDesignerSpace () {
|
||||
}
|
||||
|
||||
function buildIconByUiObjectTypeMap () {
|
||||
const relationshipArray = []
|
||||
|
||||
for (let i = 0; i < relationshipArray.length; i++) {
|
||||
let record = relationshipArray[i]
|
||||
let icon = thisObject.iconCollection.get(record[1])
|
||||
thisObject.iconByUiObjectType.set(record[0], icon)
|
||||
}
|
||||
|
||||
/* Take types-icons relationships defined at the schema */
|
||||
for (let i = 0; i < APP_SCHEMA_ARRAY.length; i++) {
|
||||
let nodeDefinition = APP_SCHEMA_ARRAY[i]
|
||||
@@ -139,7 +131,7 @@ function newDesignerSpace () {
|
||||
'bot-indicator',
|
||||
'bot-sensor',
|
||||
'time-period',
|
||||
'team',
|
||||
'data-mine',
|
||||
'procedure-loop',
|
||||
'calculations-procedure',
|
||||
'data-building-procedure',
|
||||
@@ -173,7 +165,83 @@ function newDesignerSpace () {
|
||||
'shapes-polygon',
|
||||
'data-entry',
|
||||
'data-formula',
|
||||
'clone'
|
||||
'clone',
|
||||
'exchange-account-asset',
|
||||
'exchange-account-key',
|
||||
'user-keys',
|
||||
'user-assets',
|
||||
'asset',
|
||||
'exchange-accounts',
|
||||
'user-account',
|
||||
'market',
|
||||
'exchange-assets',
|
||||
'crypto-exchanges',
|
||||
'crypto-exchange',
|
||||
'exchange-markets',
|
||||
'charting-space',
|
||||
'time-line-chart',
|
||||
'time-frame-scale',
|
||||
'time-scale',
|
||||
'rate-scale',
|
||||
'time-machine',
|
||||
'data-product',
|
||||
'single-market-data',
|
||||
'data-storage',
|
||||
'dataset',
|
||||
'viewport',
|
||||
'bitfinex',
|
||||
'binance',
|
||||
'kucoin',
|
||||
'bittrex',
|
||||
'kraken',
|
||||
'poloniex',
|
||||
'upbit',
|
||||
'monero',
|
||||
'tether',
|
||||
'tron',
|
||||
'stellar',
|
||||
'qtum',
|
||||
'neo',
|
||||
'litecoin',
|
||||
'ethereum-classic',
|
||||
'ethereum',
|
||||
'eos',
|
||||
'dash',
|
||||
'cardano',
|
||||
'bitcoin-cash',
|
||||
'bitcoin',
|
||||
'binance-coin',
|
||||
'trend',
|
||||
'oscillator',
|
||||
'moving-average',
|
||||
'histogram',
|
||||
'band',
|
||||
'volume',
|
||||
'candles',
|
||||
'bitmex',
|
||||
'liquid',
|
||||
'hitbtc',
|
||||
'us-dollar',
|
||||
'distance-to-parent-200',
|
||||
'distance-to-parent-150',
|
||||
'distance-to-parent-100',
|
||||
'distance-to-parent-050',
|
||||
'distance-to-parent-025',
|
||||
'distance-to-parent-000',
|
||||
'angle-to-parent-360',
|
||||
'angle-to-parent-180',
|
||||
'angle-to-parent-090',
|
||||
'angle-to-parent-045',
|
||||
'angle-to-parent-000',
|
||||
'data-mining',
|
||||
'initial-definition',
|
||||
'next-phase-event',
|
||||
'testing-environment',
|
||||
'production-environment',
|
||||
'task-manager',
|
||||
'session-based-data',
|
||||
'session-independent-data',
|
||||
'session-reference'
|
||||
]
|
||||
|
||||
for (let i = 0; i < iconsNames.length; i++) {
|
||||
@@ -196,7 +264,6 @@ function newDesignerSpace () {
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (visible !== true) { return }
|
||||
thisObject.workspace.physics()
|
||||
}
|
||||
|
||||
|
||||
+5
-32
@@ -9,9 +9,7 @@ function newFloatingSpace () {
|
||||
|
||||
let thisObject = {
|
||||
floatingLayer: undefined, // This is the array of floatingObjects being displayed
|
||||
profileBalls: undefined,
|
||||
uiObjectConstructor: undefined,
|
||||
noteSets: undefined,
|
||||
container: undefined,
|
||||
oneScreenUp: oneScreenUp,
|
||||
oneScreenDown: oneScreenDown,
|
||||
@@ -21,7 +19,6 @@ function newFloatingSpace () {
|
||||
fitIntoVisibleArea: fitIntoVisibleArea,
|
||||
isThisPointVisible: isThisPointVisible,
|
||||
isItFar: isItFar,
|
||||
warmUp: warmUp,
|
||||
makeVisible: makeVisible,
|
||||
makeInvisible: makeInvisible,
|
||||
draw: draw,
|
||||
@@ -41,7 +38,6 @@ function newFloatingSpace () {
|
||||
|
||||
let devicePixelRatio = window.devicePixelRatio
|
||||
const SPACE_SIZE = 50000
|
||||
const WARM_UP_LIMIT = 10000
|
||||
|
||||
thisObject.container.frame.width = SPACE_SIZE
|
||||
thisObject.container.frame.height = SPACE_SIZE
|
||||
@@ -49,7 +45,6 @@ function newFloatingSpace () {
|
||||
thisObject.container.frame.position.y = browserCanvas.height / 2 - thisObject.container.frame.height / 2
|
||||
|
||||
let visible = false
|
||||
let warmingUpCounter = 0
|
||||
|
||||
const PERCENTAGE_OF_SCREEN_FOR_DISPLACEMENT = 25
|
||||
let eventSubscriptionId
|
||||
@@ -60,15 +55,11 @@ function newFloatingSpace () {
|
||||
thisObject.container.eventHandler.stopListening(eventSubscriptionId)
|
||||
|
||||
thisObject.floatingLayer.finalize()
|
||||
thisObject.profileBalls.finalize()
|
||||
thisObject.uiObjectConstructor.finalize()
|
||||
thisObject.noteSets.finalize()
|
||||
thisObject.container.finalize()
|
||||
|
||||
thisObject.floatingLayer = undefined
|
||||
thisObject.profileBalls = undefined
|
||||
thisObject.uiObjectConstructor = undefined
|
||||
thisObject.noteSets = undefined
|
||||
thisObject.container = undefined
|
||||
}
|
||||
|
||||
@@ -76,36 +67,16 @@ function newFloatingSpace () {
|
||||
thisObject.floatingLayer = newFloatingLayer()
|
||||
thisObject.floatingLayer.initialize()
|
||||
|
||||
thisObject.profileBalls = newProfileBalls()
|
||||
thisObject.profileBalls.initialize(thisObject.floatingLayer)
|
||||
|
||||
thisObject.noteSets = newNoteSets()
|
||||
thisObject.noteSets.initialize(thisObject.floatingLayer)
|
||||
|
||||
thisObject.uiObjectConstructor = newUiObjectConstructor()
|
||||
thisObject.uiObjectConstructor.initialize(thisObject.floatingLayer)
|
||||
|
||||
eventSubscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseWheel', onMouseWheel)
|
||||
}
|
||||
|
||||
function warmUp () {
|
||||
warmingUpCounter = 0
|
||||
}
|
||||
|
||||
function isItFar (payload, dontCheckParent) {
|
||||
/* If for any reason the paylaod is undefined we return false */
|
||||
if (payload === undefined) { return false }
|
||||
|
||||
/*
|
||||
We need a warm up in order to allow all objects to stabilize into a consistant state.
|
||||
After that we will start evaluating which ones are too far from the current user view.
|
||||
*/
|
||||
|
||||
if (warmingUpCounter < WARM_UP_LIMIT) {
|
||||
warmingUpCounter++
|
||||
return false
|
||||
}
|
||||
|
||||
let radarFactor = 2 // How big is the margin
|
||||
|
||||
/* If the chain parent is not far, they we dont consither this far. */
|
||||
@@ -117,9 +88,11 @@ function newFloatingSpace () {
|
||||
|
||||
/* Exceptions that are never considered far. */
|
||||
if (
|
||||
payload.node.type === 'Definition' ||
|
||||
payload.node.type === 'Trading System' ||
|
||||
payload.node.type === 'Network' ||
|
||||
payload.node.type === 'Team'
|
||||
payload.node.type === 'Crypto Ecosystem' ||
|
||||
payload.node.type === 'Charting Space' ||
|
||||
payload.node.type === 'Data Mine'
|
||||
) {
|
||||
return false
|
||||
}
|
||||
@@ -272,7 +245,7 @@ function newFloatingSpace () {
|
||||
}
|
||||
|
||||
function physics () {
|
||||
if (visible === true || warmingUpCounter < WARM_UP_LIMIT) {
|
||||
if (visible === true) {
|
||||
browserZoomPhysics()
|
||||
thisObject.floatingLayer.physics()
|
||||
}
|
||||
|
||||
+234
-66
@@ -8,6 +8,8 @@ function newPanelsSpace () {
|
||||
let thisObject = {
|
||||
visible: true,
|
||||
container: undefined,
|
||||
makeVisible: makeVisible,
|
||||
makeInvisible: makeInvisible,
|
||||
createNewPanel: createNewPanel,
|
||||
destroyPanel: destroyPanel,
|
||||
getPanel: getPanel,
|
||||
@@ -23,10 +25,8 @@ function newPanelsSpace () {
|
||||
thisObject.container = container
|
||||
thisObject.container.isDraggeable = false
|
||||
|
||||
container.displacement.containerName = 'Panels Space'
|
||||
container.frame.containerName = 'Panels Space'
|
||||
|
||||
panelsMap = new Map()
|
||||
return thisObject
|
||||
|
||||
function initialize () {
|
||||
@@ -35,58 +35,65 @@ function newPanelsSpace () {
|
||||
|
||||
}
|
||||
|
||||
function createNewPanel (pType, pParameters, pOwner, pSession, pPanelCode) {
|
||||
function createNewPanel (pType, pParameters, pOwner, pSession) {
|
||||
let panel
|
||||
|
||||
switch (pType) {
|
||||
|
||||
case 'Time Control Panel':
|
||||
case 'Layers Panel':
|
||||
{
|
||||
panel = newTimeControlPanel()
|
||||
panel.initialize()
|
||||
break
|
||||
}
|
||||
|
||||
case 'Products Panel':
|
||||
{
|
||||
panel = newProductsPanel()
|
||||
panel.fitFunction = canvas.chartSpace.fitIntoVisibleArea
|
||||
panel = newLayersPanel()
|
||||
panel.fitFunction = canvas.chartSpace.fitFunction
|
||||
panel.container.isVisibleFunction = canvas.chartSpace.isThisPointVisible
|
||||
panel.type = 'Layers Panel'
|
||||
break
|
||||
}
|
||||
case 'Plotter Panel':
|
||||
{
|
||||
if (pPanelCode !== undefined) {
|
||||
if (pParameters.panelNode.code.isLegacy !== true) {
|
||||
panel = newPlotterPanel()
|
||||
panel.fitFunction = canvas.chartSpace.fitIntoVisibleArea
|
||||
panel.fitFunction = canvas.chartSpace.fitFunction
|
||||
panel.container.isVisibleFunction = canvas.chartSpace.isThisPointVisible
|
||||
panel.session = pSession
|
||||
panel.initialize(pPanelCode)
|
||||
panel.initialize(pParameters.panelNode)
|
||||
} else {
|
||||
panel = getNewPlotterPanel(pParameters.devTeam, pParameters.plotterCodeName, pParameters.moduleCodeName, pParameters.panelCodeName)
|
||||
panel.fitFunction = canvas.chartSpace.fitIntoVisibleArea
|
||||
panel = getNewPlotterPanel(pParameters.dataMine, pParameters.plotterCodeName, pParameters.moduleCodeName, pParameters.panelNode.code.codeName)
|
||||
panel.fitFunction = canvas.chartSpace.fitFunction
|
||||
panel.container.isVisibleFunction = canvas.chartSpace.isThisPointVisible
|
||||
panel.session = pSession
|
||||
panel.initialize()
|
||||
}
|
||||
|
||||
panel.type = 'Plotter Panel'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let panelArray = panelsMap.get(pOwner)
|
||||
if (panelArray === undefined) {
|
||||
panelArray = []
|
||||
panelsMap.set(pOwner, panelArray)
|
||||
}
|
||||
|
||||
panelArray.push(panel)
|
||||
panel.owner = pOwner
|
||||
thisObject.panels.push(panel)
|
||||
|
||||
panel.handle = Math.floor((Math.random() * 10000000) + 1)
|
||||
|
||||
return panel.handle
|
||||
}
|
||||
|
||||
function makeVisible (owner, type) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
if (panel.owner === owner && panel.type === type) {
|
||||
panel.isVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeInvisible (owner, type) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
if (panel.owner === owner && panel.type === type) {
|
||||
panel.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function destroyPanel (pPanelHandle) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
@@ -102,15 +109,12 @@ function newPanelsSpace () {
|
||||
}
|
||||
}
|
||||
|
||||
function getPanel (pPanelHandle, pOwner) {
|
||||
thisObject.panels = panelsMap.get(pOwner)
|
||||
if (thisObject.panels != undefined) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
function getPanel (pPanelHandle) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
|
||||
if (panel.handle === pPanelHandle) {
|
||||
return panel
|
||||
}
|
||||
if (panel.handle === pPanelHandle) {
|
||||
return panel
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,33 +122,203 @@ function newPanelsSpace () {
|
||||
function physics () {
|
||||
if (thisObject.visible !== true) { return }
|
||||
|
||||
childrenPhysics()
|
||||
positioningPhysics()
|
||||
}
|
||||
|
||||
function childrenPhysics () {
|
||||
if (thisObject.panels !== undefined) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
if (panel.physics !== undefined) {
|
||||
panel.physics()
|
||||
let owner = canvas.chartSpace.inViewport.get(panel.owner)
|
||||
if (owner !== undefined) {
|
||||
if (panel.physics !== undefined) {
|
||||
panel.physics()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function positioningPhysics () {
|
||||
if (thisObject.panels !== undefined) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
|
||||
/* setting the speed of the panel */
|
||||
if (panel.container.speed === undefined) {
|
||||
panel.container.speed = {
|
||||
x: 2,
|
||||
y: 2
|
||||
}
|
||||
}
|
||||
|
||||
/* Trying to move the panel and see if it is possible */
|
||||
let centerPoint = {
|
||||
x: panel.container.frame.position.x,
|
||||
y: panel.container.frame.position.y
|
||||
}
|
||||
centerPoint.x = centerPoint.x + panel.container.frame.width / 2
|
||||
centerPoint.y = centerPoint.y + panel.container.frame.height / 2
|
||||
|
||||
/* Lets see which quadrant the panel is at */
|
||||
let verticalLine = (canvas.chartSpace.viewport.visibleArea.topRight.x - canvas.chartSpace.viewport.visibleArea.topLeft.x) / 2 + canvas.chartSpace.viewport.visibleArea.topLeft.x
|
||||
let horizontalLine = (canvas.chartSpace.viewport.visibleArea.bottomRight.y - canvas.chartSpace.viewport.visibleArea.topRight.y) / 2 + canvas.chartSpace.viewport.visibleArea.topRight.y
|
||||
|
||||
if (panel.panelTabButton !== undefined) {
|
||||
if (panel.panelTabButton.status === 'up') {
|
||||
if (centerPoint.x < verticalLine) {
|
||||
panel.gravitatesTowards = 'topLeft'
|
||||
} else {
|
||||
panel.gravitatesTowards = 'topRight'
|
||||
}
|
||||
} else {
|
||||
if (centerPoint.x < verticalLine) {
|
||||
panel.gravitatesTowards = 'bottomLeft'
|
||||
} else {
|
||||
panel.gravitatesTowards = 'bottomRight'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (centerPoint.x < verticalLine && centerPoint.y < horizontalLine) {
|
||||
panel.gravitatesTowards = 'topLeft'
|
||||
}
|
||||
if (centerPoint.x >= verticalLine && centerPoint.y < horizontalLine) {
|
||||
panel.gravitatesTowards = 'topRight'
|
||||
}
|
||||
if (centerPoint.x < verticalLine && centerPoint.y >= horizontalLine) {
|
||||
panel.gravitatesTowards = 'bottomLeft'
|
||||
}
|
||||
if (centerPoint.x >= verticalLine && centerPoint.y >= horizontalLine) {
|
||||
panel.gravitatesTowards = 'bottomRight'
|
||||
}
|
||||
}
|
||||
|
||||
/* According to the quadrant we push the panels to the sides */
|
||||
if (panel.gravitatesTowards === 'topLeft' || panel.gravitatesTowards === 'bottomLeft') {
|
||||
panel.container.frame.position.x = panel.container.frame.position.x - panel.container.speed.x
|
||||
isOverlapping(i, panel.container)
|
||||
if (panel.container.frame.position.x < 0) {
|
||||
panel.container.frame.position.x = 0
|
||||
}
|
||||
} else {
|
||||
panel.container.frame.position.x = panel.container.frame.position.x + panel.container.speed.x
|
||||
isOverlapping(i, panel.container)
|
||||
if (panel.container.frame.position.x + panel.container.frame.width > browserCanvas.width) {
|
||||
panel.container.frame.position.x = browserCanvas.width - panel.container.frame.width
|
||||
}
|
||||
}
|
||||
if (panel.container.frame.height <= canvas.chartSpace.viewport.visibleArea.bottomRight.y - canvas.chartSpace.viewport.visibleArea.topRight.y) {
|
||||
if (panel.gravitatesTowards === 'topLeft' || panel.gravitatesTowards === 'topRight') {
|
||||
panel.container.frame.position.y = panel.container.frame.position.y - panel.container.speed.y
|
||||
isOverlapping(i, panel.container)
|
||||
if (panel.container.frame.position.y < canvas.chartSpace.viewport.visibleArea.topLeft.y) {
|
||||
panel.container.frame.position.y = canvas.chartSpace.viewport.visibleArea.topLeft.y
|
||||
}
|
||||
} else {
|
||||
panel.container.frame.position.y = panel.container.frame.position.y + panel.container.speed.y
|
||||
isOverlapping(i, panel.container)
|
||||
if (panel.container.frame.position.y + panel.container.frame.height > canvas.chartSpace.viewport.visibleArea.bottomRight.y) {
|
||||
panel.container.frame.position.y = canvas.chartSpace.viewport.visibleArea.bottomRight.y - panel.container.frame.height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isOverlapping (currentIndex, currentContainer) {
|
||||
let corner1 = {
|
||||
x: currentContainer.frame.position.x,
|
||||
y: currentContainer.frame.position.y
|
||||
}
|
||||
let corner2 = {
|
||||
x: currentContainer.frame.position.x + currentContainer.frame.width,
|
||||
y: currentContainer.frame.position.y
|
||||
}
|
||||
let corner3 = {
|
||||
x: currentContainer.frame.position.x + currentContainer.frame.width,
|
||||
y: currentContainer.frame.position.y + currentContainer.frame.height
|
||||
}
|
||||
let corner4 = {
|
||||
x: currentContainer.frame.position.x,
|
||||
y: currentContainer.frame.position.y + currentContainer.frame.height
|
||||
}
|
||||
|
||||
for (let i = 0; i < currentIndex; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
if (panel.isVisible === true) {
|
||||
if (isThisPointInsideThisFrame(corner1, panel.container.frame) === true) {
|
||||
pushOut(currentContainer, panel.container, panel.gravitatesTowards)
|
||||
}
|
||||
if (isThisPointInsideThisFrame(corner2, panel.container.frame) === true) {
|
||||
pushOut(currentContainer, panel.container, panel.gravitatesTowards)
|
||||
}
|
||||
if (isThisPointInsideThisFrame(corner3, panel.container.frame) === true) {
|
||||
pushOut(currentContainer, panel.container, panel.gravitatesTowards)
|
||||
}
|
||||
if (isThisPointInsideThisFrame(corner4, panel.container.frame) === true) {
|
||||
pushOut(currentContainer, panel.container, panel.gravitatesTowards)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pushOut (currentContainer, controlContainer, corner) {
|
||||
switch (corner) {
|
||||
case 'topLeft': {
|
||||
currentContainer.frame.position.x = controlContainer.frame.position.x + controlContainer.frame.width
|
||||
break
|
||||
}
|
||||
case 'topRight': {
|
||||
currentContainer.frame.position.x = controlContainer.frame.position.x - currentContainer.frame.width
|
||||
break
|
||||
}
|
||||
case 'bottomLeft': {
|
||||
currentContainer.frame.position.x = controlContainer.frame.position.x + controlContainer.frame.width
|
||||
break
|
||||
}
|
||||
case 'bottomRight': {
|
||||
currentContainer.frame.position.x = controlContainer.frame.position.x - currentContainer.frame.width
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isThisPointInsideThisFrame (point, frame) {
|
||||
let corner1 = {
|
||||
x: frame.position.x,
|
||||
y: frame.position.y
|
||||
}
|
||||
let corner2 = {
|
||||
x: frame.position.x + frame.width,
|
||||
y: frame.position.y
|
||||
}
|
||||
let corner3 = {
|
||||
x: frame.position.x + frame.width,
|
||||
y: frame.position.y + frame.height
|
||||
}
|
||||
let corner4 = {
|
||||
x: frame.position.x,
|
||||
y: frame.position.y + frame.height
|
||||
}
|
||||
if (point.x >= corner1.x && point.y >= corner1.y && point.x <= corner3.x && point.y <= corner3.y) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
if (thisObject.visible !== true) { return }
|
||||
|
||||
thisObject.container.frame.draw(false, false)
|
||||
|
||||
thisObject.panels = panelsMap.get('Global')
|
||||
if (thisObject.panels !== undefined) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
panel.draw()
|
||||
}
|
||||
}
|
||||
|
||||
thisObject.panels = panelsMap.get(window.CHART_ON_FOCUS)
|
||||
if (thisObject.panels !== undefined) {
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
for (let i = 0; i < thisObject.panels.length; i++) {
|
||||
let panel = thisObject.panels[i]
|
||||
let owner = canvas.chartSpace.inViewport.get(panel.owner)
|
||||
if (owner !== undefined) {
|
||||
panel.draw()
|
||||
}
|
||||
}
|
||||
@@ -154,26 +328,20 @@ function newPanelsSpace () {
|
||||
if (thisObject.visible !== true) { return }
|
||||
|
||||
let container
|
||||
|
||||
/*
|
||||
|
||||
We search for the container of panels in the oposite direction than we do it for drawing them,
|
||||
so panels overlapping others are picked firt although they are drawn last.
|
||||
|
||||
*/
|
||||
if (thisObject.panels !== undefined) {
|
||||
for (var i = thisObject.panels.length - 1; i >= 0; i--) {
|
||||
container = thisObject.panels[i].getContainer(point)
|
||||
|
||||
if (container !== undefined) {
|
||||
/* We found an inner container which has the point. We return it. */
|
||||
|
||||
return container
|
||||
}
|
||||
/*
|
||||
We search for the container of panels in the oposite direction than we do it for drawing them,
|
||||
so panels overlapping others are picked firt although they are drawn last.
|
||||
*/
|
||||
for (let i = thisObject.panels.length - 1; i >= 0; i--) {
|
||||
let panel = thisObject.panels[i]
|
||||
let owner = canvas.chartSpace.inViewport.get(panel.owner)
|
||||
if (owner !== undefined) {
|
||||
container = panel.getContainer(point)
|
||||
}
|
||||
if (container !== undefined) {
|
||||
return container
|
||||
}
|
||||
}
|
||||
/* The point does not belong to any inner container, so we return the current container. */
|
||||
|
||||
return thisObject.container
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -18,7 +18,7 @@ function newTopSpace () {
|
||||
return thisObject
|
||||
|
||||
function initialize () {
|
||||
window.canvasApp.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
}
|
||||
|
||||
function resize () {
|
||||
@@ -27,7 +27,7 @@ function newTopSpace () {
|
||||
|
||||
container.frame.position.x = 0
|
||||
try {
|
||||
container.frame.position.y = viewPort.visibleArea.bottomLeft.y
|
||||
container.frame.position.y = canvas.chartSpace.viewport.visibleArea.bottomLeft.y
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ function newTopSpace () {
|
||||
browserCanvasContext.beginPath()
|
||||
|
||||
browserCanvasContext.rect(0, 0, thisObject.container.frame.width, thisObject.container.frame.height)
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.RUSTED_RED + ', ' + opacity + ')'
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.PATINATED_TURQUOISE + ', ' + opacity + ')'
|
||||
|
||||
browserCanvasContext.closePath()
|
||||
|
||||
|
||||
+5
-6
@@ -19,7 +19,6 @@ function newSplashScreen () {
|
||||
|
||||
resize()
|
||||
|
||||
container.displacement.containerName = 'Splash Screen'
|
||||
container.frame.containerName = 'Splash Screen'
|
||||
|
||||
container.frame.position.x = 0
|
||||
@@ -46,7 +45,7 @@ function newSplashScreen () {
|
||||
|
||||
logo.src = window.canvasApp.urlPrefix + 'Images/Superalgos-logo-horz-sm-t.png'
|
||||
|
||||
window.canvasApp.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
canvas.eventHandler.listenToEvent('Browser Resized', resize)
|
||||
}
|
||||
|
||||
function resize () {
|
||||
@@ -126,7 +125,7 @@ function newSplashScreen () {
|
||||
|
||||
fontSize = 15
|
||||
|
||||
title = 'Trading Automation System'
|
||||
title = 'Beta'
|
||||
|
||||
titlePoint = {
|
||||
x: thisObject.container.frame.width / 2 - title.length / 2 * fontSize * FONT_ASPECT_RATIO - 20,
|
||||
@@ -134,7 +133,7 @@ function newSplashScreen () {
|
||||
}
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.font = 'Saira'
|
||||
browserCanvasContext.font = 'Saira Condensed'
|
||||
browserCanvasContext.fillStyle = 'rgba(0, 0, 0, ' + opacity + ')'
|
||||
browserCanvasContext.fillText(title, titlePoint.x, titlePoint.y)
|
||||
}
|
||||
@@ -144,14 +143,14 @@ function newSplashScreen () {
|
||||
|
||||
/* First we check if this point is inside this space. */
|
||||
|
||||
if (this.container.frame.isThisPointHere(point) === true) {
|
||||
if (thisObject.container.frame.isThisPointHere(point) === true) {
|
||||
/* Now we see which is the inner most container that has it */
|
||||
|
||||
// add validation of inner most containers here.
|
||||
|
||||
/* The point does not belong to any inner container, so we return the current container. */
|
||||
|
||||
return this.container
|
||||
return thisObject.container
|
||||
} else {
|
||||
/* This point does not belong to this space. */
|
||||
|
||||
|
||||
+104
-87
@@ -1,3 +1,86 @@
|
||||
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 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]
|
||||
if (period[0] === pTimeFrame) {
|
||||
return period[1]
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < marketFilesPeriods.length; i++) {
|
||||
let period = marketFilesPeriods[i]
|
||||
if (period[0] === pTimeFrame) {
|
||||
return period[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function download (filename, text) {
|
||||
let element = document.createElement('a')
|
||||
@@ -14,20 +97,15 @@ function transformThisPoint (point, container) {
|
||||
|
||||
point = container.frame.frameThisPoint(point)
|
||||
|
||||
/* We add the possible displacement */
|
||||
/* We pass this point through the canvas.chartSpace.viewport lends, meaning we apply the canvas.chartSpace.viewport zoom and displacement. */
|
||||
|
||||
point = container.displacement.displaceThisPoint(point)
|
||||
|
||||
/* We viewport Transformation. */
|
||||
|
||||
point = viewPort.zoomThisPoint(point)
|
||||
point = canvas.chartSpace.viewport.transformThisPoint(point)
|
||||
|
||||
return point
|
||||
}
|
||||
|
||||
function unTransformThisPoint (point, container) {
|
||||
point = viewPort.unzoomThisPoint(point)
|
||||
point = container.displacement.undisplaceThisPoint(point)
|
||||
point = canvas.chartSpace.viewport.unTransformThisPoint(point)
|
||||
point = container.frame.unframeThisPoint(point)
|
||||
|
||||
return point
|
||||
@@ -46,114 +124,53 @@ function pad (str, max) {
|
||||
return str.length < max ? pad('0' + str, max) : str
|
||||
}
|
||||
|
||||
function getDateFromPoint (point, container, timeLineCoordinateSystem) {
|
||||
function getDateFromPoint (point, container, coordinateSystem) {
|
||||
point = unTransformThisPoint(point, container)
|
||||
point = timeLineCoordinateSystem.unInverseTransform(point, container.frame.height)
|
||||
point = coordinateSystem.unInverseTransform(point, container.frame.height)
|
||||
|
||||
let date = new Date(point.x)
|
||||
|
||||
return date
|
||||
}
|
||||
|
||||
function getRateFromPoint (point, container, timeLineCoordinateSystem) {
|
||||
function getRateFromPoint (point, container, coordinateSystem) {
|
||||
point = unTransformThisPoint(point, container)
|
||||
point = timeLineCoordinateSystem.unInverseTransform(point, container.frame.height)
|
||||
point = coordinateSystem.unInverseTransform(point, container.frame.height)
|
||||
|
||||
return point.y
|
||||
}
|
||||
|
||||
function getMilisecondsFromPoint (point, container, timeLineCoordinateSystem) {
|
||||
function getMilisecondsFromPoint (point, container, coordinateSystem) {
|
||||
point = unTransformThisPoint(point, container)
|
||||
point = timeLineCoordinateSystem.unInverseTransform(point, container.frame.height)
|
||||
point = coordinateSystem.unInverseTransform(point, container.frame.height)
|
||||
|
||||
return point.x
|
||||
}
|
||||
|
||||
function saveUserPosition (container, timeLineCoordinateSystem, position) {
|
||||
if (position === undefined) {
|
||||
position = {
|
||||
x: (viewPort.visibleArea.bottomRight.x - viewPort.visibleArea.topLeft.x) / 2,
|
||||
y: (viewPort.visibleArea.bottomRight.y - viewPort.visibleArea.topLeft.y) / 2
|
||||
}
|
||||
}
|
||||
|
||||
let userPosition = {
|
||||
date: getDateFromPoint(position, container, timeLineCoordinateSystem),
|
||||
rate: getRateFromPoint(position, container, timeLineCoordinateSystem),
|
||||
market: DEFAULT_MARKET,
|
||||
zoom: viewPort.zoomTargetLevel
|
||||
}
|
||||
|
||||
window.localStorage.setItem('userPosition', JSON.stringify(userPosition))
|
||||
}
|
||||
|
||||
function getUserPosition (timeLineCoordinateSystem) {
|
||||
let savedPosition = window.localStorage.getItem('userPosition')
|
||||
let userPosition
|
||||
|
||||
if (savedPosition === null) {
|
||||
userPosition = {
|
||||
date: (new Date()).toString(),
|
||||
rate: timeLineCoordinateSystem.max.y / 2,
|
||||
market: DEFAULT_MARKET,
|
||||
zoom: INITIAL_ZOOM_LEVEL
|
||||
}
|
||||
} else {
|
||||
userPosition = JSON.parse(savedPosition)
|
||||
}
|
||||
|
||||
userPosition.point = {
|
||||
x: (new Date(userPosition.date)).valueOf(),
|
||||
y: userPosition.rate
|
||||
}
|
||||
|
||||
return userPosition
|
||||
}
|
||||
|
||||
function moveToUserPosition (container, timeLineCoordinateSystem, ignoreX, ignoreY, center, considerZoom) {
|
||||
let userPosition = getUserPosition(timeLineCoordinateSystem)
|
||||
|
||||
if (considerZoom === true) {
|
||||
viewPort.newZoomLevel(userPosition.zoom)
|
||||
}
|
||||
|
||||
INITIAL_TIME_PERIOD = recalculatePeriod(userPosition.zoom)
|
||||
NEW_SESSION_INITIAL_DATE = new Date(userPosition.date)
|
||||
|
||||
function moveToUserPosition (container, currentDate, currentRate, coordinateSystem, ignoreX, ignoreY, mousePosition) {
|
||||
let targetPoint = {
|
||||
x: (new Date(userPosition.date)).valueOf(),
|
||||
y: userPosition.rate
|
||||
x: currentDate.valueOf(),
|
||||
y: currentRate
|
||||
}
|
||||
|
||||
/* Put this po int in the coordinate system of the viewPort */
|
||||
|
||||
targetPoint = timeLineCoordinateSystem.transformThisPoint(targetPoint)
|
||||
/* Put this point in the coordinate system of the canvas.chartSpace.viewport */
|
||||
targetPoint = coordinateSystem.transformThisPoint(targetPoint)
|
||||
targetPoint = transformThisPoint(targetPoint, container)
|
||||
|
||||
let centerPoint
|
||||
if (center !== undefined) {
|
||||
centerPoint = {
|
||||
x: center.x,
|
||||
y: center.y
|
||||
}
|
||||
} else {
|
||||
centerPoint = {
|
||||
x: (viewPort.visibleArea.bottomRight.x - viewPort.visibleArea.topLeft.x) / 2,
|
||||
y: (viewPort.visibleArea.bottomRight.y - viewPort.visibleArea.topLeft.y) / 2
|
||||
}
|
||||
}
|
||||
let displaceVector
|
||||
|
||||
/* Lets calculate the displace vector, from the point we want at the center, to the current center. */
|
||||
let targetNoZoom = canvas.chartSpace.viewport.unTransformThisPoint(targetPoint)
|
||||
let mouseNoZoom = canvas.chartSpace.viewport.unTransformThisPoint(mousePosition)
|
||||
|
||||
let displaceVector = {
|
||||
x: centerPoint.x - targetPoint.x,
|
||||
y: centerPoint.y - targetPoint.y
|
||||
displaceVector = {
|
||||
x: mouseNoZoom.x - targetNoZoom.x,
|
||||
y: mouseNoZoom.y - targetNoZoom.y
|
||||
}
|
||||
|
||||
if (ignoreX) { displaceVector.x = 0 }
|
||||
if (ignoreY) { displaceVector.y = 0 }
|
||||
|
||||
viewPort.displace(displaceVector)
|
||||
container.displace(displaceVector)
|
||||
}
|
||||
|
||||
function removeTime (datetime) {
|
||||
|
||||
@@ -104,3 +104,38 @@ function roundedCornersBackground (params) {
|
||||
browserCanvasContext.strokeStyle = 'rgba(' + params.borderColor + ', ' + params.opacity + ')'
|
||||
browserCanvasContext.stroke()
|
||||
}
|
||||
|
||||
function drawLabel (label, xFactor, yFactor, xOffset, yOffset, fontSize, container) {
|
||||
if (label === undefined) { return }
|
||||
let fontOffset = label.length * fontSize * FONT_ASPECT_RATIO + 10
|
||||
|
||||
let labelPoint = {
|
||||
x: container.frame.width * xFactor + xOffset - fontOffset / 2,
|
||||
y: container.frame.height * yFactor + yOffset
|
||||
}
|
||||
|
||||
labelPoint = container.frame.frameThisPoint(labelPoint)
|
||||
|
||||
browserCanvasContext.font = fontSize + 'px ' + UI_FONT.PRIMARY
|
||||
browserCanvasContext.fillStyle = 'rgba(' + UI_COLOR.WHITE + ', 1)'
|
||||
|
||||
browserCanvasContext.fillText(label, labelPoint.x, labelPoint.y)
|
||||
}
|
||||
|
||||
function drawIcon (icon, xFactor, yFactor, xOffset, yOffset, imageSize, container) {
|
||||
if (icon !== undefined) {
|
||||
if (icon.canDrawIcon === true) {
|
||||
let imagePosition = {
|
||||
x: container.frame.width * xFactor + xOffset - imageSize / 2,
|
||||
y: container.frame.height * yFactor + yOffset - imageSize / 2
|
||||
}
|
||||
|
||||
imagePosition = container.frame.frameThisPoint(imagePosition)
|
||||
browserCanvasContext.drawImage(
|
||||
icon, imagePosition.x,
|
||||
imagePosition.y,
|
||||
imageSize,
|
||||
imageSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user