@devexperts/dxcharts-lite
Version:
169 lines (168 loc) • 7.73 kB
JavaScript
/*
* Copyright (C) 2019 - 2025 Devexperts Solutions IE Limited
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { BehaviorSubject } from 'rxjs';
import { ChartBaseElement } from '../../model/chart-base-element';
import { CanvasElement, CHART_UUID } from '../../canvas/canvas-bounds-container';
import { isMobile } from '../../utils/device/browser.utils';
export class CrossToolModel extends ChartBaseElement {
get currentHover() {
return this.currentHoverSubject.getValue();
}
set currentHover(value) {
this.currentHoverSubject.next(value);
}
constructor(config, crossToolCanvasModel, crossEventProducer, hoverProducer, canvasBoundsContainer, baselineModel) {
super();
this.config = config;
this.crossToolCanvasModel = crossToolCanvasModel;
this.crossEventProducer = crossEventProducer;
this.hoverProducer = hoverProducer;
this.canvasBoundsContainer = canvasBoundsContainer;
this.baselineModel = baselineModel;
// the main hover object which will be presented on UI
this.currentHoverSubject = new BehaviorSubject(null);
}
/**
* Sets the type of the CrossTool object.
*
* @param {CrossToolType} type - The type of the CrossTool object.
* @returns {void}
*/
setType(type) {
this.config.type = type;
}
/**
* Method to activate the cross tool.
* It subscribes to the hoverProducer's hover event and updates the crosstool.
*/
doActivate() {
super.doActivate();
this.addRxSubscription(this.hoverProducer.hoverSubject.subscribe(hover => {
if (this.crossEventProducer.crossSubject.getValue() !== null && hover !== null) {
isMobile() ? this.updateCrossToolMobile(hover) : this.updateCrossTool(hover);
}
else {
this.currentHover = null;
}
this.fireDraw();
}));
// don't change mobile crosstool hover and position if baseline is being dragged
this.addRxSubscription(this.baselineModel.dragPredicate.subscribe(isDragging => {
if (!isMobile()) {
return;
}
if (isDragging) {
this.hoverProducer.deactivate();
}
else {
// set the crosstool position before baseline drag happened to keep hover the same
const crossToolInfo = this.crossEventProducer.crossToolTouchInfo;
// if cross tool is on chart - update hover with it's coordinates
if (crossToolInfo.isSet) {
this.crossEventProducer.crossSubject.next([
crossToolInfo.temp.x,
crossToolInfo.temp.y,
CHART_UUID,
]);
}
this.hoverProducer.activate();
}
}));
}
/**
* This method is used to fire the draw event of the crossToolCanvasModel if the type is not 'none'.
* @private
*/
fireDraw() {
if (this.config.type !== 'none') {
this.crossToolCanvasModel.fireDraw();
}
}
/**
* Updates the current hover position with the provided hover object.
* @param {Object} hover - The hover object containing the x and y coordinates and time formatted.
* @param magnetTarget {MagnetTarget}
* @param {number} hover.x - The x coordinate of the hover.
* @param {number} hover.y - The y coordinate of the hover.
* @param {string} hover.timeFormatted - The formatted time of the hover.
* @param {Object} hover.candleHover - The candle hover object containing the open, close, high, low and closestOHLCY coordinates.
* @param {number} hover.candleHover.openY - The y coordinate of the open price of the candle.
* @param {number} hover.candleHover.closeY - The y coordinate of the close price of the candle.
* @param {number} hover.candleHover.highY - The y coordinate of the high price of the candle.
* @param {number} hover.candleHover.lowY - The y coordinate of the low price of the candle.
* @param {number} hover.candleHover.closestOHLCY - The y coordinate of the closest OHLC price of the candle.
* @returns {void}
*/
updateCrossTool(hover, magnetTarget = this.config.magnetTarget) {
if (this.currentHover === null) {
this.currentHover = { x: hover.x, y: 0, time: hover.timeFormatted, paneId: hover.paneId };
}
else {
this.currentHover.x = hover.x;
this.currentHover.time = hover.timeFormatted;
}
if (hover.candleHover && hover.paneId === CHART_UUID) {
switch (magnetTarget) {
case 'O':
this.currentHover.y = hover.candleHover.openY;
break;
case 'C':
this.currentHover.y = hover.candleHover.closeY;
break;
case 'H':
this.currentHover.y = hover.candleHover.highY;
break;
case 'L':
this.currentHover.y = hover.candleHover.lowY;
break;
case 'OHLC':
this.currentHover.y = hover.candleHover.closestOHLCY;
break;
case 'none':
this.currentHover.y = hover.y;
break;
}
}
else {
this.currentHover.y = hover.y;
}
this.currentHover.paneId = hover.paneId;
this.currentHoverSubject.next(this.currentHover);
}
updateCrossToolMobile(hover) {
var _a;
// mobile crosstool works only after long touch event
if (!this.hoverProducer.longTouchActivatedSubject.getValue()) {
return;
}
const { fixed, temp, isSet } = this.crossEventProducer.crossToolTouchInfo;
// long touch makes crosstool fixed and the further moving will place crosstool under the current hover coordinates (ordinary logic)
// if crosstool is already set (long touch end event happened) the moving of chart will move crosstool according to it's initial (fixed position)
if (!isSet) {
this.updateCrossTool(hover);
return;
}
// additional crosstool move logic
const paneBounds = this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(hover.paneId));
const offset = 5;
// take a difference inbetween current hover and temporary crosstool coordinates
const xDiff = hover.x - temp.x;
const yDiff = hover.y - temp.y;
// apply the difference to the fixed coordinates
const rawX = fixed.x + xDiff;
const rawY = fixed.y + yDiff;
const paneYStart = paneBounds.y + offset;
const paneYEnd = paneBounds.y + paneBounds.height - offset;
// check for chart bounds and don't move crosstool outside of it
const x = rawX < offset ? offset : rawX > paneBounds.width - offset ? paneBounds.width - offset : rawX;
const y = rawY < paneYStart ? paneYStart : rawY > paneYEnd ? paneYEnd : rawY;
const crossToolHover = (_a = this.hoverProducer.createHover(x, y, hover.paneId)) !== null && _a !== void 0 ? _a : hover;
const updatedHover = Object.assign(Object.assign({}, crossToolHover), { x,
y });
this.crossEventProducer.crossToolHover = updatedHover;
this.updateCrossTool(updatedHover);
}
}