Files
Superalgos/ChartsSpace/TimelineChart.js
T

387 lines
12 KiB
JavaScript

function newTimelineChart () {
const MODULE_NAME = 'Timeline Chart'
const INFO_LOG = false
const INTENSIVE_LOG = false
const ERROR_LOG = true
const logger = newWebDebugLog()
logger.fileName = MODULE_NAME
let timeLineCoordinateSystem
let timeFrame = INITIAL_TIME_PERIOD
let datetime = NEW_SESSION_INITIAL_DATE
let thisObject = {
container: undefined,
fitFunction: undefined,
timeFrameScale: undefined,
payload: undefined,
physics: physics,
setDatetime: setDatetime,
drawBackground: drawBackground,
draw: draw,
getContainer: getContainer,
initialize: initialize,
finalize: finalize
}
thisObject.fitFunction = canvas.chartSpace.fitIntoVisibleArea
let initializationReady = false
let productsPanel
/* Background */
let logoBaseAsset
let logoQuotedAsset
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 onOffsetChangedEventSuscriptionId
let onZoomChangedEventSuscriptionId
let onMouseOverEventSuscriptionId
let onMouseNotOverEventSuscriptionId
let timeFrameScaleEventSuscriptionId
let timeFrameScaleMouseOverEventSuscriptionId
let mouse = {
position: {
x: 0,
y: 0
}
}
setupContainer()
return thisObject
function setupContainer () {
thisObject.container = newContainer()
thisObject.container.initialize(MODULE_NAME)
thisObject.container.detectMouseOver = true
}
function finalize () {
if (thisObject.timeFrameScale !== undefined) {
finalizeTimeFrameScale()
}
viewPort.eventHandler.stopListening(onOffsetChangedEventSuscriptionId)
viewPort.eventHandler.stopListening(onZoomChangedEventSuscriptionId)
thisObject.container.eventHandler.stopListening(onMouseOverEventSuscriptionId)
thisObject.container.eventHandler.stopListening(onMouseNotOverEventSuscriptionId)
plotterManager.finalize()
plotterManager = undefined
canvas.panelsSpace.destroyPanel(productsPanelHandle)
thisObject.container.finalize()
thisObject.container = undefined
thisObject.payload = undefined
mouse = undefined
}
function finalizeTimeFrameScale () {
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleEventSuscriptionId)
thisObject.timeFrameScale.container.eventHandler.stopListening(timeFrameScaleMouseOverEventSuscriptionId)
thisObject.timeFrameScale.finalize()
thisObject.timeFrameScale = undefined
}
function initialize (pExchange, pMarket, pTimeLineCoordinateSystem, callBackFunction) {
try {
/* We load the logow we will need for the background. */
exchange = pExchange
market = pMarket
timeLineCoordinateSystem = pTimeLineCoordinateSystem
let panelOwner = exchange + ' ' + market.quotedAsset + '/' + market.baseAsset
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
}
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)
timeFrame = INITIAL_TIME_PERIOD
datetime = NEW_SESSION_INITIAL_DATE
/* Event Subscriptions - we need this events to be fired first here and then in active Plotters. */
onOffsetChangedEventSuscriptionId = viewPort.eventHandler.listenToEvent('Offset Changed', onOffsetChanged)
onZoomChangedEventSuscriptionId = 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 (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
}
onMouseOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseOver', onMouseOver)
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. */
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.visible = true
thisObject.timeFrameScale.onMouseOverSomeTimeMachineContainer(event)
}
mouse.position.x = event.x
mouse.position.y = event.y
saveUserPosition(thisObject.container, timeLineCoordinateSystem, event)
}
onMouseNotOverEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseNotOver', onMouseNotOver)
function onMouseNotOver (event) {
/* This event is inherited from the Time Machine */
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.visible = false
}
}
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 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 Changed', function (event) {
let currentTimeFrame = timeFrame
timeFrame = event.timeFrame
if (timeFrame !== currentTimeFrame) {
plotterManager.setTimeFrame(timeFrame)
}
})
thisObject.timeFrameScale.initialize(timeLineCoordinateSystem, thisObject.container)
timeFrameScaleMouseOverEventSuscriptionId = thisObject.timeFrameScale.container.eventHandler.listenToEvent('onMouseOver', timeFrameScaleMouseOver)
function timeFrameScaleMouseOver (event) {
thisObject.container.eventHandler.raiseEvent('onChildrenMouseOver', event)
saveUserPosition(thisObject.container, timeLineCoordinateSystem, event)
}
}
function onZoomChanged (event) {
if (initializationReady === true) {
recalculateCurrentDatetime()
// saveUserPosition(thisObject.container, timeLineCoordinateSystem)
}
}
function setDatetime (pDatetime) {
/* 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)
}
}
function onOffsetChanged () {
if (initializationReady === true) {
if (thisObject.container.frame.isInViewPort()) {
recalculateCurrentDatetime()
// saveUserPosition(thisObject.container, timeLineCoordinateSystem)
}
}
}
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: (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)
}
function getContainer (point) {
let container
if (thisObject.timeFrameScale !== undefined) {
container = thisObject.timeFrameScale.getContainer(point)
}
return container
}
function physics () {
thisObjectPhysics()
childrenPhysics()
syncWithDesignerScales()
}
function thisObjectPhysics () {
}
function syncWithDesignerScales () {
if (thisObject.payload.node.timeFrameScale === undefined && thisObject.timeFrameScale !== undefined) {
finalizeTimeFrameScale()
}
if (thisObject.payload.node.timeFrameScale !== undefined && thisObject.timeFrameScale === undefined) {
initializeTimeFrameScale()
}
}
function childrenPhysics () {
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.physics()
}
}
function tooTiny () {
if (viewPort.zoomLevel < Math.trunc(-28.25 * 100) / 100) {
return true
} else {
return false
}
}
function tooSmall () {
if (viewPort.zoomLevel < Math.trunc(-27.25 * 100) / 100) {
return true
} else {
return false
}
}
function drawBackground () {
if (thisObject.container.frame.isInViewPort()) {
if (window.CHART_ON_FOCUS === '') {
window.CHART_ON_FOCUS = exchange + ' ' + market.quotedAsset + '/' + market.baseAsset
}
drawChartsBackground()
plotterManager.draw()
}
}
function draw () {
if (thisObject.container.frame.isInViewPort()) {
if (thisObject.timeFrameScale !== undefined) {
thisObject.timeFrameScale.draw()
}
}
}
function drawChartsBackground () {
/* We will paint some transparent background here. */
let opacity = '0.5'
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()
}
}