520 lines
17 KiB
JavaScript
520 lines
17 KiB
JavaScript
|
|
let browserCanvas; // This is the canvas object of the browser.
|
|
let browserCanvasContext; // The context of the canvas object.
|
|
|
|
let stepsInitializationCounter = 0; // This counter the initialization steps required to be able to turn off the splash screen.
|
|
let marketInitializationCounter = 0; // This counter the initialization of markets required to be able to turn off the splash screen.
|
|
let splashScreenNeeded = true;
|
|
|
|
function newCanvas() {
|
|
|
|
/*
|
|
The canvas object represents a layer on top of the browser canvas object.
|
|
|
|
Graphically, thiscanvas object has 4 spaces:
|
|
|
|
1) The "Top Space": It is where Team and User information is displayed.
|
|
|
|
2) The "Chart Space": It is where the charts are plotted.
|
|
|
|
3) The "Floating Space": It is where floating elements live. There is a physics engine for this layer that allows these elements to flow.
|
|
|
|
4) The "Panels Space": It is where panels live. --> This space has yet to be develop, currently pannels are somehow at the Chart Space.
|
|
|
|
5) The "Bottom Space": Includes the breakpoint bar and a toolbar.
|
|
|
|
All these spaces are child objects of the Canvas object.
|
|
|
|
Canvas
|
|
|
|
|
|
|
|
---> topSpace
|
|
|
|
|
|
|
|
---> chartSpace
|
|
|
|
|
|
|
|
---> flaotingSpace
|
|
|
|
|
|
|
|
---> panelsSpace
|
|
|
|
|
|
|
|
---> bottomSpace
|
|
*/
|
|
|
|
const MODULE_NAME = "Canvas";
|
|
const INFO_LOG = false;
|
|
const ERROR_LOG = true;
|
|
const logger = newWebDebugLog();
|
|
logger.fileName = MODULE_NAME;
|
|
|
|
/* Mouse event related variables. */
|
|
|
|
let containerDragStarted = false;
|
|
let floatingObjectDragStarted = false;
|
|
let floatingObjectBeingDragged;
|
|
let containerBeingDragged;
|
|
let viewPortBeingDragged = false;
|
|
|
|
let dragVector = {
|
|
downX: 0,
|
|
downY: 0,
|
|
upX: 0,
|
|
upY: 0
|
|
};
|
|
|
|
/* canvas object */
|
|
|
|
let thisObject = {
|
|
eventHandler: undefined,
|
|
topSpace: undefined,
|
|
chartSpace: undefined,
|
|
floatingSpace: undefined,
|
|
panelsSpace: undefined,
|
|
bottomSpace: undefined,
|
|
animation: undefined,
|
|
initialize: initialize
|
|
};
|
|
|
|
thisObject.eventHandler = newEventHandler();
|
|
|
|
let splashScreen;
|
|
|
|
return thisObject;
|
|
|
|
function initialize(callBackFunction) {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] initialize -> Entering function."); }
|
|
|
|
initializeBrowserCanvas();
|
|
|
|
addCanvasEvents();
|
|
|
|
/* Instantiate all the children spaces of Canvas object */
|
|
|
|
thisObject.topSpace = newTopSpace();
|
|
thisObject.topSpace.initialize();
|
|
|
|
thisObject.panelsSpace = newPanelsSpace();
|
|
thisObject.panelsSpace.initialize();
|
|
|
|
thisObject.floatingSpace = newFloatingSpace();
|
|
thisObject.floatingSpace.initialize();
|
|
|
|
thisObject.chartSpace = newChartSpace();
|
|
thisObject.chartSpace.initialize(onCharSpaceInitialized);
|
|
|
|
thisObject.bottomSpace = newBottomSpace();
|
|
thisObject.bottomSpace.initialize();
|
|
|
|
function onCharSpaceInitialized(err) {
|
|
viewPort.raiseEvents(); // These events will impacts on objects just initialized.
|
|
}
|
|
|
|
/* Splash Screen */
|
|
|
|
splashScreen = newSplashScreen();
|
|
splashScreen.initialize();
|
|
|
|
let animation = newAnimation();
|
|
animation.initialize(onAnimationInitialized);
|
|
|
|
function onAnimationInitialized(err) {
|
|
|
|
thisObject.animation = animation;
|
|
|
|
/* Here we add all the functions that will be called during the animation cycle. */
|
|
|
|
animation.addCallBackFunction("Chart Space", thisObject.chartSpace.draw, onFunctionAdded);
|
|
animation.addCallBackFunction("Floating Space", thisObject.floatingSpace.floatingLayer.physicsLoop, onFunctionAdded);
|
|
animation.addCallBackFunction("Panels Space", thisObject.panelsSpace.draw, onFunctionAdded);
|
|
animation.addCallBackFunction("Splash Screen", splashScreen.draw, onFunctionAdded);
|
|
animation.addCallBackFunction("ViewPort Animate", viewPort.animate, onFunctionAdded);
|
|
animation.addCallBackFunction("ViewPort Draw", viewPort.draw, onFunctionAdded);
|
|
animation.addCallBackFunction("Bottom Space", thisObject.bottomSpace.draw, onFunctionAdded);
|
|
animation.addCallBackFunction("Top Space", thisObject.topSpace.draw, onFunctionAdded);
|
|
animation.start(onStart);
|
|
|
|
function onFunctionAdded(err) {
|
|
|
|
if (err.result === GLOBAL.DEFAULT_FAIL_RESPONSE.result) {
|
|
|
|
animation.stop();
|
|
|
|
if (ERROR_LOG === true) { logger.write("[ERROR] initialize -> onAnimationInitialized -> onFunctionAdded -> Animation Stopped since a vital funtion could not be added."); }
|
|
|
|
/* Display some Error Page here. */
|
|
}
|
|
}
|
|
|
|
function onStart(err) {
|
|
|
|
switch (err.result) {
|
|
case GLOBAL.DEFAULT_OK_RESPONSE.result: {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] initialize -> onAnimationInitialized -> onStart -> Received OK Response."); }
|
|
callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
case GLOBAL.DEFAULT_FAIL_RESPONSE.result: {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] initialize -> onAnimationInitialized -> onStart -> Received FAIL Response."); }
|
|
callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
default: {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] initialize -> onAnimationInitialized -> onStart -> Received Unexpected Response."); }
|
|
callBackFunction(err);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function initializeBrowserCanvas() {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] initializeBrowserCanvas -> Entering function."); }
|
|
|
|
browserCanvas = document.getElementById('canvas');
|
|
browserCanvasContext = browserCanvas.getContext('2d');
|
|
|
|
let body = document.getElementById('body');
|
|
|
|
browserCanvas.width = window.innerWidth;
|
|
browserCanvas.height = window.innerHeight;
|
|
browserCanvas.style.border = "none";
|
|
|
|
viewPort.initialize();
|
|
}
|
|
|
|
function addCanvasEvents() {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] addCanvasEvents -> Entering function."); }
|
|
|
|
/* Mouse down and up events to control the drag of the canvas. */
|
|
|
|
browserCanvas.addEventListener('mousedown', onMouseDown, false);
|
|
browserCanvas.addEventListener('mouseup', onMouseUp, false);
|
|
browserCanvas.addEventListener('mousemove', onMouseMove, false);
|
|
browserCanvas.addEventListener('click', onMouseClick, false);
|
|
|
|
/* Mouse wheel events. */
|
|
|
|
if (browserCanvas.addEventListener) {
|
|
// IE9, Chrome, Safari, Opera
|
|
browserCanvas.addEventListener("mousewheel", onMouseWheel, false);
|
|
// Firefox
|
|
browserCanvas.addEventListener("DOMMouseScroll", onMouseWheel, false);
|
|
}
|
|
// IE 6/7/8
|
|
else browserCanvas.attachEvent("onmousewheel", onMouseWheel);
|
|
|
|
}
|
|
|
|
function onMouseDown(event) {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] onMouseDown -> Entering function."); }
|
|
|
|
/*
|
|
|
|
There are four types of elements that can be dragged.
|
|
|
|
1. Panels.
|
|
2. Floating Elements (Currently only FloatingObjects).
|
|
3. Charts.
|
|
4. The Viewport.
|
|
|
|
We eveluate each space in order to see if they are holding the element being dragged, and we fallout at the Viewport.
|
|
|
|
*/
|
|
|
|
dragVector.downX = event.pageX;
|
|
dragVector.downY = event.pageY;
|
|
|
|
let point = {
|
|
x: event.pageX,
|
|
y: event.pageY
|
|
};
|
|
|
|
let container;
|
|
|
|
/* We check if the mouse is over an element of the Top Space / */
|
|
|
|
container = thisObject.topSpace.getContainer(point);
|
|
|
|
if (container !== undefined && container.isDraggeable === true) {
|
|
|
|
containerBeingDragged = container;
|
|
containerDragStarted = true;
|
|
return;
|
|
}
|
|
|
|
/* We check if the mouse is over an element of the Bottom Space / */
|
|
|
|
container = thisObject.bottomSpace.getContainer(point);
|
|
|
|
if (container !== undefined && container.isDraggeable === true) {
|
|
|
|
containerBeingDragged = container;
|
|
containerDragStarted = true;
|
|
return;
|
|
}
|
|
|
|
/* We check if the mouse is over a panel/ */
|
|
|
|
container = thisObject.panelsSpace.getContainer(point);
|
|
|
|
if (container !== undefined && container.isDraggeable === true) {
|
|
|
|
containerBeingDragged = container;
|
|
containerDragStarted = true;
|
|
return;
|
|
}
|
|
|
|
/* We check if the mouse is over a floatingObject/ */
|
|
|
|
floatingObjectBeingDragged = thisObject.floatingSpace.floatingLayer.isInside(event.pageX, event.pageY);
|
|
|
|
if (floatingObjectBeingDragged >= 0) {
|
|
floatingObjectDragStarted = true;
|
|
return;
|
|
}
|
|
|
|
/* If it is not, then we check if it is over any of the existing containers at the Chart Space. */
|
|
|
|
container = thisObject.chartSpace.getContainer(point);
|
|
|
|
if (container !== undefined && container.isDraggeable === true) {
|
|
|
|
containerBeingDragged = container;
|
|
containerDragStarted = true;
|
|
return;
|
|
}
|
|
|
|
viewPortBeingDragged = true;
|
|
}
|
|
|
|
function onMouseClick(event) {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] onMouseClick -> Entering function."); }
|
|
|
|
let point = {
|
|
x: event.pageX,
|
|
y: event.pageY
|
|
};
|
|
|
|
let container;
|
|
|
|
/* We check if the mouse is over an element of the Top Space / */
|
|
|
|
container = thisObject.topSpace.getContainer(point);
|
|
|
|
if (container !== undefined && container.isClickeable === true) {
|
|
|
|
container.eventHandler.raiseEvent('onMouseClick', point);
|
|
return;
|
|
}
|
|
|
|
/* We check if the mouse is over an element of the Bottom Space / */
|
|
|
|
container = thisObject.bottomSpace.getContainer(point);
|
|
|
|
if (container !== undefined && container.isClickeable === true) {
|
|
|
|
container.eventHandler.raiseEvent('onMouseClick', point);
|
|
return;
|
|
}
|
|
|
|
/* We check if the mouse is over a panel/ */
|
|
|
|
container = thisObject.panelsSpace.getContainer(point);
|
|
|
|
if (container !== undefined && container.isClickeable === true) {
|
|
|
|
container.eventHandler.raiseEvent('onMouseClick', point);
|
|
return;
|
|
}
|
|
|
|
/* We check if the mouse is over a floatingObject/ */
|
|
|
|
let floatingObjectBeingClicked = thisObject.floatingSpace.floatingLayer.isInside(event.pageX, event.pageY);
|
|
|
|
if (floatingObjectBeingClicked >= 0) {
|
|
|
|
/* Right now we do nothing with this. */
|
|
return;
|
|
|
|
}
|
|
|
|
/* If it is not, then we check if it is over any of the existing containers at the Chart Space. */
|
|
|
|
container = thisObject.chartSpace.getContainer(point);
|
|
|
|
if (container !== undefined && container.isClickeable === true) {
|
|
|
|
container.eventHandler.raiseEvent('onMouseClick', point);
|
|
return;
|
|
}
|
|
}
|
|
|
|
function onMouseUp(event) {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] onMouseUp -> Entering function."); }
|
|
|
|
if (containerDragStarted || viewPortBeingDragged || floatingObjectDragStarted) {
|
|
|
|
thisObject.eventHandler.raiseEvent("Drag Finished", undefined);
|
|
|
|
}
|
|
|
|
/* Turn off all the possible things that can be dragged. */
|
|
|
|
containerDragStarted = false;
|
|
floatingObjectDragStarted = false;
|
|
viewPortBeingDragged = false;
|
|
|
|
containerBeingDragged = undefined;
|
|
|
|
browserCanvas.style.cursor = "auto";
|
|
|
|
}
|
|
|
|
function onMouseMove(event) {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] onMouseMove -> Entering function."); }
|
|
|
|
viewPort.mousePosition.x = event.pageX;
|
|
viewPort.mousePosition.y = event.pageY;
|
|
|
|
if (containerDragStarted === true || floatingObjectDragStarted === true || viewPortBeingDragged === true) {
|
|
|
|
if (floatingObjectDragStarted === true) {
|
|
|
|
if (thisObject.floatingSpace.floatingLayer.isInsideFloatingObject(floatingObjectBeingDragged, event.pageX, event.pageY) === false) {
|
|
|
|
/* This means that the user stop moving the mouse and the floatingObject floatingObject out of the pointer.
|
|
In this case we cancell the drag operation . */
|
|
|
|
floatingObjectDragStarted = false;
|
|
browserCanvas.style.cursor = "auto";
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
dragVector.upX = event.pageX;
|
|
dragVector.upY = event.pageY;
|
|
|
|
checkDrag();
|
|
}
|
|
}
|
|
|
|
function onMouseWheel(event) {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] onMouseWheel -> Entering function."); }
|
|
|
|
// cross-browser wheel delta
|
|
var event = window.event || event; // old IE support
|
|
let delta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail));
|
|
|
|
/* We try first with panels. */
|
|
|
|
let panelContainer = canvas.panelsSpace.getContainer({ x: event.pageX, y: event.pageY });
|
|
|
|
if (panelContainer !== undefined && panelContainer.isWheelable === true) {
|
|
|
|
panelContainer.eventHandler.raiseEvent("Mouse Wheel", event.wheelDelta);
|
|
return false; // This instructs the browser not to take the event and scroll the page.
|
|
}
|
|
|
|
/* We try second with floating objects. */
|
|
|
|
let floatingObjectIndex = canvas.floatingSpace.floatingLayer.isInside(event.pageX, event.pageY);
|
|
|
|
if (floatingObjectIndex > 0) {
|
|
|
|
canvas.floatingSpace.floatingLayer.changeTargetRepulsion(event.wheelDelta);
|
|
|
|
} else {
|
|
|
|
viewPort.applyZoom(delta);
|
|
|
|
}
|
|
|
|
return false; // This instructs the browser not to take the event and scroll the page.
|
|
}
|
|
|
|
function checkDrag() {
|
|
|
|
if (INFO_LOG === true) { logger.write("[INFO] checkDrag -> Entering function."); }
|
|
|
|
if (containerDragStarted === true || floatingObjectDragStarted === true || viewPortBeingDragged === true) {
|
|
|
|
browserCanvas.style.cursor = "grabbing";
|
|
thisObject.eventHandler.raiseEvent("Dragging", undefined);
|
|
|
|
let targetFloatingObject = thisObject.floatingSpace.floatingLayer.isInside(event.pageX, event.pageY);
|
|
|
|
if (floatingObjectDragStarted) {
|
|
|
|
let floatingObject = thisObject.floatingSpace.floatingLayer.getFloatingObject(undefined, floatingObjectBeingDragged);
|
|
|
|
floatingObject.currentPosition.x = dragVector.upX;
|
|
floatingObject.currentPosition.y = dragVector.upY;
|
|
|
|
}
|
|
|
|
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 (viewPortBeingDragged) {
|
|
|
|
viewPort.displace(displaceVector);
|
|
|
|
}
|
|
|
|
if (containerBeingDragged !== undefined) {
|
|
|
|
containerBeingDragged.frame.position.x = containerBeingDragged.frame.position.x + displaceVector.x;
|
|
containerBeingDragged.frame.position.y = containerBeingDragged.frame.position.y + displaceVector.y;
|
|
|
|
}
|
|
}
|
|
|
|
/* Finally we set the starting point of the new dragVector at this current point. */
|
|
|
|
dragVector.downX = dragVector.upX;
|
|
dragVector.downY = dragVector.upY;
|
|
|
|
}
|
|
}
|
|
} |