@devexperts/dxcharts-lite 2.4.6 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chart/__tests__/model/date-time.formatter.test.d.ts +6 -0
- package/dist/chart/__tests__/model/date-time.formatter.test.js +30 -0
- package/dist/chart/canvas/canvas-bounds-container.d.ts +7 -3
- package/dist/chart/canvas/canvas-bounds-container.js +149 -105
- package/dist/chart/canvas/y-axis-bounds.container.js +4 -0
- package/dist/chart/chart.config.js +4 -4
- package/dist/chart/components/chart/chart-area-pan.handler.d.ts +1 -5
- package/dist/chart/components/chart/chart-area-pan.handler.js +1 -8
- package/dist/chart/components/dran-n-drop_helper/drag-n-drop-x.component.d.ts +0 -6
- package/dist/chart/components/dran-n-drop_helper/drag-n-drop-x.component.js +0 -8
- package/dist/chart/components/dran-n-drop_helper/drag-n-drop-y.component.d.ts +0 -5
- package/dist/chart/components/dran-n-drop_helper/drag-n-drop-y.component.js +0 -7
- package/dist/chart/components/dran-n-drop_helper/drag-n-drop.component.d.ts +0 -11
- package/dist/chart/components/dran-n-drop_helper/drag-n-drop.component.js +0 -16
- package/dist/chart/components/pan/chart-pan.component.d.ts +3 -14
- package/dist/chart/components/pan/chart-pan.component.js +7 -21
- package/dist/chart/components/pane/pane-manager.component.d.ts +29 -0
- package/dist/chart/components/pane/pane-manager.component.js +71 -8
- package/dist/chart/components/pane/pane.component.d.ts +5 -17
- package/dist/chart/components/pane/pane.component.js +11 -28
- package/dist/chart/components/resizer/bar-resizer.component.d.ts +1 -1
- package/dist/chart/components/resizer/bar-resizer.component.js +3 -1
- package/dist/chart/components/y_axis/y-axis-scale.handler.js +3 -3
- package/dist/chart/components/y_axis/y-axis.component.js +1 -1
- package/dist/chart/inputhandlers/hover-producer.component.d.ts +1 -1
- package/dist/chart/inputhandlers/main-canvas-touch.handler.d.ts +11 -2
- package/dist/chart/inputhandlers/main-canvas-touch.handler.js +34 -2
- package/dist/chart/model/baseline.model.d.ts +3 -0
- package/dist/chart/model/baseline.model.js +5 -0
- package/dist/chart/model/chart-base-element.d.ts +2 -0
- package/dist/chart/model/chart-base-element.js +2 -0
- package/dist/chart/model/date-time.formatter.d.ts +20 -3
- package/dist/chart/model/date-time.formatter.js +62 -14
- package/dist/chart/model/scale.model.d.ts +5 -0
- package/dist/chart/model/scale.model.js +9 -1
- package/dist/chart/model/scaling/constrait.functions.d.ts +5 -7
- package/dist/chart/model/scaling/constrait.functions.js +3 -3
- package/dist/chart/model/time-zone.model.js +3 -1
- package/dist/dxchart.min.js +4 -4
- package/package.json +1 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2019 - 2024 Devexperts Solutions IE Limited
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
import '../env';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2019 - 2024 Devexperts Solutions IE Limited
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
|
+
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
*/
|
|
6
|
+
import '../env';
|
|
7
|
+
import { formatDate, getShortDays, getShortMonths } from '../../model/date-time.formatter';
|
|
8
|
+
import { getDefaultConfig } from '../../chart.config';
|
|
9
|
+
import { getTimezoneOffset } from '../../utils/timezone.utils';
|
|
10
|
+
describe('Date time formatter', () => {
|
|
11
|
+
const config = getDefaultConfig();
|
|
12
|
+
const days = getShortDays(config);
|
|
13
|
+
const months = getShortMonths(config);
|
|
14
|
+
const timestamp = 1710501810500;
|
|
15
|
+
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
16
|
+
const utcTimestamp = timestamp - getTimezoneOffset(tz, timestamp);
|
|
17
|
+
const utcDate = new Date(utcTimestamp); // 03/15/2024 @ 11:23am UTC
|
|
18
|
+
describe('Timezones', () => {
|
|
19
|
+
it('should always be UTC', () => {
|
|
20
|
+
expect(getTimezoneOffset('UTC', utcTimestamp)).toBe(0);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe('Formatter', () => {
|
|
24
|
+
it('should return formatted value according to given pattern', () => {
|
|
25
|
+
expect(formatDate(utcDate, 'YYYY', days, months)).toEqual('2024');
|
|
26
|
+
expect(formatDate(utcDate, 'HH:mm:ss', days, months)).toEqual('11:23:30');
|
|
27
|
+
expect(formatDate(utcDate, 'dd.MM.YYYY', days, months)).toEqual('15.03.2024');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -44,6 +44,7 @@ export declare class CanvasElement {
|
|
|
44
44
|
static Y_AXIS: string;
|
|
45
45
|
}
|
|
46
46
|
export declare const DEFAULT_BOUNDS: Bounds;
|
|
47
|
+
export declare const DEFAULT_MIN_PANE_HEIGHT = 20;
|
|
47
48
|
/**
|
|
48
49
|
* This component listens EVENT_DRAW and recalculates bounds of canvas chart elements.
|
|
49
50
|
* {@link getBounds} method will always give actual placement of element you want.
|
|
@@ -61,6 +62,7 @@ export declare class CanvasBoundsContainer {
|
|
|
61
62
|
canvasOnPageLocation: Bounds;
|
|
62
63
|
panesOrder: Array<string>;
|
|
63
64
|
panesOrderChangedSubject: Subject<string[]>;
|
|
65
|
+
paneVisibilityChangedSubject: Subject<void>;
|
|
64
66
|
xAxisHeight: number | undefined;
|
|
65
67
|
yAxisWidths: YAxisWidths;
|
|
66
68
|
leftRatio: number;
|
|
@@ -85,8 +87,7 @@ export declare class CanvasBoundsContainer {
|
|
|
85
87
|
* @param {Record<string, number>} heightRatios - An object containing the height ratios to be set.
|
|
86
88
|
* @returns {void}
|
|
87
89
|
* @throws {Error} If the sum of the height ratios is not equal to 1.
|
|
88
|
-
|
|
89
|
-
*/
|
|
90
|
+
*/
|
|
90
91
|
overrideChartHeightRatios(heightRatios: Record<string, number>): void;
|
|
91
92
|
/**
|
|
92
93
|
* Moves a pane up in the panesOrder array.
|
|
@@ -109,12 +110,14 @@ export declare class CanvasBoundsContainer {
|
|
|
109
110
|
* result: ['3', '2', '1']
|
|
110
111
|
*/
|
|
111
112
|
reorderPanes(newPanesOrder: string[]): void;
|
|
113
|
+
hidePaneBounds(uuid: string): void;
|
|
114
|
+
showPaneBounds(uuid: string): void;
|
|
112
115
|
/**
|
|
113
116
|
* Removes the bounds of a pane with the given uuid from the canvas element.
|
|
114
117
|
* @param {string} uuid - The uuid of the pane to remove.
|
|
115
118
|
* @returns {void}
|
|
116
119
|
*/
|
|
117
|
-
|
|
120
|
+
removePaneBounds(uuid: string): void;
|
|
118
121
|
/**
|
|
119
122
|
* Recalculates the bounds of the chart elements based on the current configuration and canvas size.
|
|
120
123
|
* The function updates the bounds of the canvas, the main chart, the panes, the y-axis, and the chart with y-axis.
|
|
@@ -326,6 +329,7 @@ export declare class CanvasBoundsContainer {
|
|
|
326
329
|
*/
|
|
327
330
|
setMainCandleSeries(candleSeries: CandleSeriesModel): void;
|
|
328
331
|
}
|
|
332
|
+
export declare const getHeightRatios: (pecLength: number) => [number, number];
|
|
329
333
|
export declare const isInBounds: (point: Point, bounds: Bounds) => boolean;
|
|
330
334
|
export declare const isInVerticalBounds: (y: number, bounds: Bounds) => boolean;
|
|
331
335
|
export declare const limitYToBounds: (y: Pixel, bounds: Bounds) => number;
|
|
@@ -40,7 +40,7 @@ CanvasElement.CHART = CanvasElement.PANE_UUID(CHART_UUID);
|
|
|
40
40
|
CanvasElement.Y_AXIS = CanvasElement.PANE_UUID_Y_AXIS(CHART_UUID);
|
|
41
41
|
export { CanvasElement };
|
|
42
42
|
export const DEFAULT_BOUNDS = { x: 0, y: 0, pageX: 0, pageY: 0, width: 0, height: 0 };
|
|
43
|
-
const DEFAULT_MIN_PANE_HEIGHT = 20;
|
|
43
|
+
export const DEFAULT_MIN_PANE_HEIGHT = 20;
|
|
44
44
|
const N_MAP_H = 35;
|
|
45
45
|
const N_MAP_BUTTON_W = 15;
|
|
46
46
|
const KNOTS_W_MOBILE_MULTIPLIER = 1.5;
|
|
@@ -72,6 +72,7 @@ export class CanvasBoundsContainer {
|
|
|
72
72
|
// holds ordered "top to bottom" array of panes UUID's (studies in past)
|
|
73
73
|
this.panesOrder = [];
|
|
74
74
|
this.panesOrderChangedSubject = new Subject();
|
|
75
|
+
this.paneVisibilityChangedSubject = new Subject();
|
|
75
76
|
// both will be calculated based on font/content size
|
|
76
77
|
this.xAxisHeight = undefined;
|
|
77
78
|
this.yAxisWidths = {
|
|
@@ -120,8 +121,7 @@ export class CanvasBoundsContainer {
|
|
|
120
121
|
* @param {Record<string, number>} heightRatios - An object containing the height ratios to be set.
|
|
121
122
|
* @returns {void}
|
|
122
123
|
* @throws {Error} If the sum of the height ratios is not equal to 1.
|
|
123
|
-
|
|
124
|
-
*/
|
|
124
|
+
*/
|
|
125
125
|
overrideChartHeightRatios(heightRatios) {
|
|
126
126
|
const resultRatio = Object.assign(Object.assign({}, this.graphsHeightRatio), heightRatios);
|
|
127
127
|
const ratioSum = Object.values(resultRatio).reduce((sum, ratio) => sum + ratio, 0);
|
|
@@ -174,12 +174,33 @@ export class CanvasBoundsContainer {
|
|
|
174
174
|
this.recalculateBounds();
|
|
175
175
|
this.panesOrderChangedSubject.next(this.panesOrder);
|
|
176
176
|
}
|
|
177
|
+
hidePaneBounds(uuid) {
|
|
178
|
+
this.graphsHeightRatio[uuid] = 0;
|
|
179
|
+
this.recalculatePanesHeightRatios();
|
|
180
|
+
this.paneVisibilityChangedSubject.next();
|
|
181
|
+
}
|
|
182
|
+
showPaneBounds(uuid) {
|
|
183
|
+
if (uuid === CHART_UUID) {
|
|
184
|
+
const [defaultChartHeightRatio] = getHeightRatios(this.panesOrder.length - 1);
|
|
185
|
+
this.graphsHeightRatio[uuid] = defaultChartHeightRatio;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
// when pane is hidden it has ratio of 0
|
|
189
|
+
// when we want pane to be visible again we want `recalculatePanesHeightRatios` function
|
|
190
|
+
// to treat it as a new pane
|
|
191
|
+
// to do so we need to delete its ratio (which is 0 because it is hidden) from graphsHeightRatio
|
|
192
|
+
// NOTE: CHART_UUID pane is exception, it is treated differently and should always have some ratio
|
|
193
|
+
delete this.graphsHeightRatio[uuid];
|
|
194
|
+
}
|
|
195
|
+
this.recalculatePanesHeightRatios();
|
|
196
|
+
this.paneVisibilityChangedSubject.next();
|
|
197
|
+
}
|
|
177
198
|
/**
|
|
178
199
|
* Removes the bounds of a pane with the given uuid from the canvas element.
|
|
179
200
|
* @param {string} uuid - The uuid of the pane to remove.
|
|
180
201
|
* @returns {void}
|
|
181
202
|
*/
|
|
182
|
-
|
|
203
|
+
removePaneBounds(uuid) {
|
|
183
204
|
arrayRemove2(this.panesOrder, uuid);
|
|
184
205
|
delete this.graphsHeightRatio[uuid];
|
|
185
206
|
delete this.bounds[CanvasElement.PANE_UUID(uuid)];
|
|
@@ -223,13 +244,14 @@ export class CanvasBoundsContainer {
|
|
|
223
244
|
const chartWidth = canvas.width - totalYAxisWidthLeft - totalYAxisWidthRight;
|
|
224
245
|
let nextY = initialY;
|
|
225
246
|
// panes
|
|
247
|
+
const firstVisiblePaneIdx = this.panesOrder.findIndex(uuid => this.graphsHeightRatio[uuid] > 0);
|
|
226
248
|
this.panesOrder.forEach((uuid, index) => {
|
|
227
249
|
var _a;
|
|
228
250
|
const paneHeightRatio = this.graphsHeightRatio[this.panesOrder[index]];
|
|
229
|
-
// hide resizer for first pane
|
|
230
|
-
const resizerVisible = this.config.components.paneResizer.visible && index !== 0;
|
|
251
|
+
// hide resizer for the first visible pane
|
|
231
252
|
const resizerUUID = CanvasElement.PANE_UUID_RESIZER(uuid);
|
|
232
253
|
const paneUUID = CanvasElement.PANE_UUID(uuid);
|
|
254
|
+
const resizerVisible = this.config.components.paneResizer.visible && index > firstVisiblePaneIdx && paneHeightRatio > 0;
|
|
233
255
|
if (resizerVisible) {
|
|
234
256
|
upsertBounds(this.bounds, resizerUUID, 0, nextY, canvas.width, paneResizerHeight, this.canvasOnPageLocation);
|
|
235
257
|
}
|
|
@@ -237,7 +259,7 @@ export class CanvasBoundsContainer {
|
|
|
237
259
|
upsertBounds(this.bounds, resizerUUID, 0, 0, 0, 0, this.canvasOnPageLocation);
|
|
238
260
|
}
|
|
239
261
|
const paneYStart = nextY + (resizerVisible ? paneResizerHeight : 0);
|
|
240
|
-
const paneBounds = upsertBounds(this.bounds, paneUUID, paneXStart, paneYStart, chartWidth, chartHeight * paneHeightRatio - (resizerVisible ?
|
|
262
|
+
const paneBounds = upsertBounds(this.bounds, paneUUID, paneXStart, paneYStart, chartWidth, chartHeight * paneHeightRatio - (resizerVisible ? paneResizerHeight : 0), this.canvasOnPageLocation);
|
|
241
263
|
// y axis
|
|
242
264
|
if (this.config.components.yAxis.visible) {
|
|
243
265
|
const extents = this.yAxisBoundsContainer.extentsOrder.get(uuid);
|
|
@@ -425,34 +447,46 @@ export class CanvasBoundsContainer {
|
|
|
425
447
|
// NOTE: pec stands for panesExceptMainChart
|
|
426
448
|
const pec = [];
|
|
427
449
|
pec.push(...this.panesOrder.filter(p => p !== CHART_UUID));
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
const
|
|
434
|
-
|
|
450
|
+
const pecRatios = pec.map(uuid => this.graphsHeightRatio[uuid] === undefined ? undefined : this.graphsHeightRatio[uuid]);
|
|
451
|
+
// we should count only visible panes, to escape wheight distribution for hidden panes
|
|
452
|
+
const visiblePecRatios = pecRatios.filter(ratio => ratio !== 0);
|
|
453
|
+
const visiblePecNumber = visiblePecRatios.length;
|
|
454
|
+
// we don't count as an old PEC panes that are not visible, because they don't whey in the final result
|
|
455
|
+
const oldPecNumber = visiblePecRatios.filter(ratio => ratio !== undefined).length;
|
|
456
|
+
// if ratio in undefined for a given pane it means that it's a new pane
|
|
435
457
|
const newPecNumber = pecRatios.filter(ratio => ratio === undefined).length;
|
|
436
458
|
let freeRatioForPec = 0;
|
|
437
459
|
let freeRatio = 0;
|
|
438
460
|
let ratioForOldPec = 1;
|
|
439
461
|
let ratioForNewPec = 0;
|
|
440
462
|
if (newPecNumber > 0) {
|
|
441
|
-
[ratioForOldPec, ratioForNewPec] = getHeightRatios(
|
|
463
|
+
[ratioForOldPec, ratioForNewPec] = getHeightRatios(visiblePecNumber);
|
|
442
464
|
chartRatio *= ratioForOldPec;
|
|
443
465
|
}
|
|
466
|
+
// this means we should keep in mind only new panes
|
|
444
467
|
if (oldPecNumber === 0) {
|
|
445
468
|
chartRatio = 1 - ratioForNewPec * newPecNumber;
|
|
446
469
|
}
|
|
447
470
|
freeRatio = 1 - chartRatio - ratioForNewPec * newPecNumber;
|
|
448
|
-
|
|
471
|
+
visiblePecRatios.forEach(ratio => {
|
|
449
472
|
if (ratio) {
|
|
450
473
|
freeRatio -= ratio * ratioForOldPec;
|
|
451
474
|
}
|
|
452
475
|
});
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
476
|
+
// || 1 to escape division by zero
|
|
477
|
+
// because there's might be no visible panes except CHART
|
|
478
|
+
freeRatioForPec = freeRatio / (visiblePecNumber || 1);
|
|
479
|
+
// distribute left free ratio between new and old panes
|
|
480
|
+
const proportions = pecRatios.map(ratio => {
|
|
481
|
+
// if ratio === 0 it means, that it's hidden
|
|
482
|
+
if (ratio === 0) {
|
|
483
|
+
return ratio;
|
|
484
|
+
}
|
|
485
|
+
if (!ratio) {
|
|
486
|
+
return ratioForNewPec + freeRatioForPec;
|
|
487
|
+
}
|
|
488
|
+
return ratio * ratioForOldPec + freeRatioForPec;
|
|
489
|
+
});
|
|
456
490
|
this._graphsHeightRatio = {};
|
|
457
491
|
this.graphsHeightRatio[CHART_UUID] = chartRatio;
|
|
458
492
|
proportions.forEach((ratio, index) => {
|
|
@@ -478,88 +512,89 @@ export class CanvasBoundsContainer {
|
|
|
478
512
|
*/
|
|
479
513
|
recalculateNavigationMapElementBounds() {
|
|
480
514
|
var _a, _b, _c, _d;
|
|
481
|
-
if (this.config.components.navigationMap.visible) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
const slider = this.getBounds(CanvasElement.N_MAP_SLIDER_WINDOW);
|
|
552
|
-
slider.x = knotL.x + knotL.width;
|
|
553
|
-
slider.y = nMap.y;
|
|
554
|
-
slider.width = knotR.x - slider.x;
|
|
555
|
-
slider.height = nMap.height;
|
|
556
|
-
// chart
|
|
557
|
-
const nMapChart = this.getBounds(CanvasElement.N_MAP_CHART);
|
|
558
|
-
nMapChart.x = navMapChartStart;
|
|
559
|
-
nMapChart.y = nMap.y;
|
|
560
|
-
nMapChart.width = navMapChartWidth;
|
|
561
|
-
nMapChart.height = nMap.height;
|
|
515
|
+
if (!this.config.components.navigationMap.visible) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const nMap = this.getBounds(CanvasElement.N_MAP);
|
|
519
|
+
const { height, width } = this.config.components.navigationMap.knots;
|
|
520
|
+
const knotHeightFromConfig = height !== null && height !== void 0 ? height : 0;
|
|
521
|
+
const knotWidthFromConfig = isMobile() ? width * KNOTS_W_MOBILE_MULTIPLIER : width !== null && width !== void 0 ? width : 0;
|
|
522
|
+
const knotY = !knotHeightFromConfig ? nMap.y : nMap.y + (nMap.height - knotHeightFromConfig) / 2;
|
|
523
|
+
// time labels
|
|
524
|
+
const timeLabelsVisible = (_b = (_a = this.config.components.navigationMap) === null || _a === void 0 ? void 0 : _a.timeLabels) === null || _b === void 0 ? void 0 : _b.visible;
|
|
525
|
+
const calcLabelBounds = (timestamp) => {
|
|
526
|
+
return calcTimeLabelBounds(this.canvasModel.ctx, timestamp, this.formatterFactory, this.config)[0];
|
|
527
|
+
};
|
|
528
|
+
const candleSource = flat((_d = (_c = this.mainCandleSeries) === null || _c === void 0 ? void 0 : _c.getSeriesInViewport()) !== null && _d !== void 0 ? _d : []);
|
|
529
|
+
const leftTimeLabelWidth = timeLabelsVisible && candleSource.length ? calcLabelBounds(candleSource[0].candle.timestamp) : 0;
|
|
530
|
+
const rightTimeLabelWidth = timeLabelsVisible && candleSource.length
|
|
531
|
+
? calcLabelBounds(candleSource[candleSource.length - 1].candle.timestamp)
|
|
532
|
+
: 0;
|
|
533
|
+
const timeLabelWidth = Math.max(leftTimeLabelWidth, rightTimeLabelWidth);
|
|
534
|
+
if (timeLabelsVisible) {
|
|
535
|
+
const nMapLabelL = this.getBounds(CanvasElement.N_MAP_LABEL_L);
|
|
536
|
+
nMapLabelL.x = nMap.x;
|
|
537
|
+
nMapLabelL.y = nMap.y;
|
|
538
|
+
nMapLabelL.width = timeLabelWidth;
|
|
539
|
+
nMapLabelL.height = nMap.height;
|
|
540
|
+
const nMapLabelR = this.getBounds(CanvasElement.N_MAP_LABEL_R);
|
|
541
|
+
nMapLabelR.x = nMap.x + nMap.width - timeLabelWidth;
|
|
542
|
+
nMapLabelR.y = nMap.y;
|
|
543
|
+
nMapLabelR.width = timeLabelWidth;
|
|
544
|
+
nMapLabelR.height = nMap.height;
|
|
545
|
+
}
|
|
546
|
+
// buttons left and right
|
|
547
|
+
const nMapBtnL = this.getBounds(CanvasElement.N_MAP_BTN_L);
|
|
548
|
+
nMapBtnL.x = nMap.x + timeLabelWidth;
|
|
549
|
+
nMapBtnL.y = nMap.y;
|
|
550
|
+
nMapBtnL.width = N_MAP_BUTTON_W;
|
|
551
|
+
nMapBtnL.height = nMap.height;
|
|
552
|
+
const nMapBtnR = this.getBounds(CanvasElement.N_MAP_BTN_R);
|
|
553
|
+
nMapBtnR.x = nMap.x + nMap.width - N_MAP_BUTTON_W - timeLabelWidth;
|
|
554
|
+
nMapBtnR.y = nMap.y;
|
|
555
|
+
nMapBtnR.width = N_MAP_BUTTON_W;
|
|
556
|
+
nMapBtnR.height = nMap.height;
|
|
557
|
+
// knots
|
|
558
|
+
const navMapChartStart = nMapBtnL.x + nMapBtnL.width;
|
|
559
|
+
const navMapChartWidth = nMapBtnR.x - navMapChartStart;
|
|
560
|
+
const navMapChartEnd = navMapChartStart + navMapChartWidth;
|
|
561
|
+
const minSliderW = this.config.components.navigationMap.minSliderWindowWidth;
|
|
562
|
+
const knotW = knotWidthFromConfig !== null && knotWidthFromConfig !== void 0 ? knotWidthFromConfig : N_MAP_KNOT_W;
|
|
563
|
+
const knotH = knotHeightFromConfig !== null && knotHeightFromConfig !== void 0 ? knotHeightFromConfig : nMap.height;
|
|
564
|
+
const minDistanceBetweenKnotsX = knotW + minSliderW;
|
|
565
|
+
// Left drag button
|
|
566
|
+
const knotL = this.getBounds(CanvasElement.N_MAP_KNOT_L);
|
|
567
|
+
knotL.x = navMapChartStart + navMapChartWidth * this.leftRatio;
|
|
568
|
+
// limit left knot to min distance from right border
|
|
569
|
+
knotL.x = Math.min(knotL.x, navMapChartEnd - minDistanceBetweenKnotsX);
|
|
570
|
+
knotL.y = knotY;
|
|
571
|
+
knotL.width = knotW;
|
|
572
|
+
knotL.height = knotH;
|
|
573
|
+
// Right drag button
|
|
574
|
+
const knotR = this.getBounds(CanvasElement.N_MAP_KNOT_R);
|
|
575
|
+
knotR.x = navMapChartStart + navMapChartWidth * this.rightRatio - N_MAP_KNOT_W;
|
|
576
|
+
// limit right knot to min distance from left border
|
|
577
|
+
knotR.x = Math.max(knotR.x, navMapChartStart + minDistanceBetweenKnotsX);
|
|
578
|
+
knotR.y = knotY;
|
|
579
|
+
knotR.width = knotW;
|
|
580
|
+
knotR.height = knotH;
|
|
581
|
+
const distanceDiff = minDistanceBetweenKnotsX - (knotR.x - knotL.x);
|
|
582
|
+
// if distance between knots is less than min distance - move left knot start
|
|
583
|
+
if (distanceDiff > 0) {
|
|
584
|
+
knotL.x -= distanceDiff;
|
|
562
585
|
}
|
|
586
|
+
// slider
|
|
587
|
+
const slider = this.getBounds(CanvasElement.N_MAP_SLIDER_WINDOW);
|
|
588
|
+
slider.x = knotL.x + knotL.width;
|
|
589
|
+
slider.y = nMap.y;
|
|
590
|
+
slider.width = knotR.x - slider.x;
|
|
591
|
+
slider.height = nMap.height;
|
|
592
|
+
// chart
|
|
593
|
+
const nMapChart = this.getBounds(CanvasElement.N_MAP_CHART);
|
|
594
|
+
nMapChart.x = navMapChartStart;
|
|
595
|
+
nMapChart.y = nMap.y;
|
|
596
|
+
nMapChart.width = navMapChartWidth;
|
|
597
|
+
nMapChart.height = nMap.height;
|
|
563
598
|
}
|
|
564
599
|
/**
|
|
565
600
|
* Checks if the volumes are set to be visible and if they should be shown in a separate pane
|
|
@@ -683,11 +718,20 @@ export class CanvasBoundsContainer {
|
|
|
683
718
|
* @returns {void}
|
|
684
719
|
*/
|
|
685
720
|
doResizePaneVertically(idx, yDeltaPixels) {
|
|
686
|
-
|
|
721
|
+
// get prev visible pane index
|
|
722
|
+
let prevVisiblePaneIdx = idx - 1;
|
|
723
|
+
const prevPaneUUID = this.panesOrder[prevVisiblePaneIdx];
|
|
724
|
+
if (this._graphsHeightRatio[prevPaneUUID] <= 0) {
|
|
725
|
+
for (let i = 0; i < idx; i++) {
|
|
726
|
+
if (this._graphsHeightRatio[this.panesOrder[i]] > 0) {
|
|
727
|
+
prevVisiblePaneIdx = i;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
}
|
|
687
731
|
const allPanesHeight = this.getBounds(CanvasElement.ALL_PANES).height;
|
|
688
|
-
const minAllowedPaneHeight =
|
|
732
|
+
const minAllowedPaneHeight = DEFAULT_MIN_PANE_HEIGHT;
|
|
689
733
|
const resultPaneHeight = allPanesHeight * this.graphsHeightRatio[this.panesOrder[idx]];
|
|
690
|
-
const dependResultPaneHeight = allPanesHeight * this.graphsHeightRatio[this.panesOrder[
|
|
734
|
+
const dependResultPaneHeight = allPanesHeight * this.graphsHeightRatio[this.panesOrder[prevVisiblePaneIdx]];
|
|
691
735
|
// check if changes fit allowed minimal pane height
|
|
692
736
|
const fitPane = resultPaneHeight + yDeltaPixels > minAllowedPaneHeight;
|
|
693
737
|
const fitDependPane = dependResultPaneHeight - yDeltaPixels > minAllowedPaneHeight;
|
|
@@ -695,7 +739,7 @@ export class CanvasBoundsContainer {
|
|
|
695
739
|
// convert pixels to percent
|
|
696
740
|
const yDeltaPercent = yDeltaPixels / allPanesHeight;
|
|
697
741
|
this.graphsHeightRatio[this.panesOrder[idx]] += yDeltaPercent;
|
|
698
|
-
this.graphsHeightRatio[this.panesOrder[
|
|
742
|
+
this.graphsHeightRatio[this.panesOrder[prevVisiblePaneIdx]] -= yDeltaPercent;
|
|
699
743
|
this.recalculateBounds();
|
|
700
744
|
}
|
|
701
745
|
}
|
|
@@ -791,7 +835,7 @@ const DEFAULT_RATIOS = {
|
|
|
791
835
|
5: 0.2,
|
|
792
836
|
};
|
|
793
837
|
// NOTE: pec stands for panes except main chart
|
|
794
|
-
const getHeightRatios = (pecLength) => {
|
|
838
|
+
export const getHeightRatios = (pecLength) => {
|
|
795
839
|
var _a;
|
|
796
840
|
const chartHeightRatio = (_a = DEFAULT_RATIOS[pecLength]) !== null && _a !== void 0 ? _a : 0.4;
|
|
797
841
|
const singlePecHeightRatio = (1 - chartHeightRatio) / pecLength;
|
|
@@ -50,6 +50,10 @@ export class YAxisBoundsContainer {
|
|
|
50
50
|
this.yAxisWidthContributors.forEach(c => {
|
|
51
51
|
var _a, _b, _c;
|
|
52
52
|
const state = c.getYAxisState();
|
|
53
|
+
// if YAxis is not visible, do not add it to contributors width
|
|
54
|
+
if (!state.visible) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
53
57
|
const margin = state.labelBoxMargin.start + state.labelBoxMargin.end;
|
|
54
58
|
const width = this.getTextWidth(c.getLargestLabel()) + margin;
|
|
55
59
|
const idx = c.getYAxisIndex();
|
|
@@ -209,20 +209,20 @@ export const getDefaultConfig = () => ({
|
|
|
209
209
|
{
|
|
210
210
|
format: 'dd.MM.YYYY',
|
|
211
211
|
showWhen: {
|
|
212
|
-
periodMoreThen:
|
|
212
|
+
periodMoreThen: 24 * 60 * 60 * 1000,
|
|
213
213
|
},
|
|
214
214
|
},
|
|
215
215
|
{
|
|
216
216
|
format: 'dd.MM.YYYY HH:mm',
|
|
217
217
|
showWhen: {
|
|
218
|
-
periodLessThen:
|
|
219
|
-
periodMoreThen:
|
|
218
|
+
periodLessThen: 24 * 60 * 60 * 1000,
|
|
219
|
+
periodMoreThen: 6 * 1000,
|
|
220
220
|
},
|
|
221
221
|
},
|
|
222
222
|
{
|
|
223
223
|
format: 'dd.MM.YYYY HH:mm:ss',
|
|
224
224
|
showWhen: {
|
|
225
|
-
periodLessThen:
|
|
225
|
+
periodLessThen: 6 * 1000,
|
|
226
226
|
},
|
|
227
227
|
},
|
|
228
228
|
],
|
|
@@ -24,7 +24,6 @@ interface ChartPanningOptions {
|
|
|
24
24
|
/**
|
|
25
25
|
* ChartAreaPanHandler is a class that handles the panning and zooming of the chart area.
|
|
26
26
|
* It extends the ChartBaseElement class and has the following properties:
|
|
27
|
-
* @property {MainCanvasTouchHandler} touchHandler - An instance of the MainCanvasTouchHandler class.
|
|
28
27
|
* @property {Point} currentPoint - An object that represents the current point of the chart area.
|
|
29
28
|
* @property {number} xDraggedCandlesDelta - A number that represents the number of candles delta changed during X dragging.
|
|
30
29
|
* @property {number} lastXStart - A number that represents the last X start position.
|
|
@@ -34,7 +33,6 @@ interface ChartPanningOptions {
|
|
|
34
33
|
* @param {EventBus} bus - An instance of the EventBus class.
|
|
35
34
|
* @param {FullChartConfig} config - An instance of the FullChartConfig class.
|
|
36
35
|
* @param {ScaleModel} scaleModel - An instance of the ScaleModel class.
|
|
37
|
-
* @param {Element} mainCanvasParent - The parent element of the main canvas.
|
|
38
36
|
* @param {CanvasInputListenerComponent} canvasInputListener - An instance of the CanvasInputListenerComponent class.
|
|
39
37
|
* @param {CanvasBoundsContainer} canvasBoundsContainer - An instance of the CanvasBoundsContainer class.
|
|
40
38
|
* @param {CanvasAnimation} canvasAnimation - An instance of the CanvasAnimation class.
|
|
@@ -45,19 +43,17 @@ export declare class ChartAreaPanHandler extends ChartBaseElement {
|
|
|
45
43
|
private bus;
|
|
46
44
|
private config;
|
|
47
45
|
private scale;
|
|
48
|
-
private mainCanvasParent;
|
|
49
46
|
private canvasInputListener;
|
|
50
47
|
private canvasBoundsContainer;
|
|
51
48
|
private canvasAnimation;
|
|
52
49
|
private chartPanComponent;
|
|
53
50
|
private hitTestCanvasModel;
|
|
54
|
-
private readonly touchHandler;
|
|
55
51
|
private currentPoint;
|
|
56
52
|
xDraggedCandlesDelta: number;
|
|
57
53
|
lastXStart: number;
|
|
58
54
|
wheelThrottleTime: number;
|
|
59
55
|
chartPanningOptions: ChartPanningOptions;
|
|
60
|
-
constructor(bus: EventBus, config: FullChartConfig, scale: ScaleModel,
|
|
56
|
+
constructor(bus: EventBus, config: FullChartConfig, scale: ScaleModel, canvasInputListener: CanvasInputListenerComponent, canvasBoundsContainer: CanvasBoundsContainer, canvasAnimation: CanvasAnimation, chartPanComponent: ChartPanComponent, hitTestCanvasModel: HitTestCanvasModel);
|
|
61
57
|
/**
|
|
62
58
|
* It observes the wheel event on all panes of the canvas and throttles it to the specified time.
|
|
63
59
|
* It then calculates the zoom sensitivity based on whether the event was triggered by a touchpad or not.
|
|
@@ -7,7 +7,6 @@ import { animationFrameScheduler } from 'rxjs';
|
|
|
7
7
|
import { throttleTime, filter } from 'rxjs/operators';
|
|
8
8
|
import { VIEWPORT_ANIMATION_ID } from '../../animation/canvas-animation';
|
|
9
9
|
import { CanvasElement } from '../../canvas/canvas-bounds-container';
|
|
10
|
-
import { MainCanvasTouchHandler } from '../../inputhandlers/main-canvas-touch.handler';
|
|
11
10
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
12
11
|
import { pixelsToUnits } from '../../model/scaling/viewport.model';
|
|
13
12
|
import { deviceDetector } from '../../utils/device/device-detector.utils';
|
|
@@ -17,7 +16,6 @@ import { DragNDropYComponent } from '../dran-n-drop_helper/drag-n-drop-y.compone
|
|
|
17
16
|
/**
|
|
18
17
|
* ChartAreaPanHandler is a class that handles the panning and zooming of the chart area.
|
|
19
18
|
* It extends the ChartBaseElement class and has the following properties:
|
|
20
|
-
* @property {MainCanvasTouchHandler} touchHandler - An instance of the MainCanvasTouchHandler class.
|
|
21
19
|
* @property {Point} currentPoint - An object that represents the current point of the chart area.
|
|
22
20
|
* @property {number} xDraggedCandlesDelta - A number that represents the number of candles delta changed during X dragging.
|
|
23
21
|
* @property {number} lastXStart - A number that represents the last X start position.
|
|
@@ -27,7 +25,6 @@ import { DragNDropYComponent } from '../dran-n-drop_helper/drag-n-drop-y.compone
|
|
|
27
25
|
* @param {EventBus} bus - An instance of the EventBus class.
|
|
28
26
|
* @param {FullChartConfig} config - An instance of the FullChartConfig class.
|
|
29
27
|
* @param {ScaleModel} scaleModel - An instance of the ScaleModel class.
|
|
30
|
-
* @param {Element} mainCanvasParent - The parent element of the main canvas.
|
|
31
28
|
* @param {CanvasInputListenerComponent} canvasInputListener - An instance of the CanvasInputListenerComponent class.
|
|
32
29
|
* @param {CanvasBoundsContainer} canvasBoundsContainer - An instance of the CanvasBoundsContainer class.
|
|
33
30
|
* @param {CanvasAnimation} canvasAnimation - An instance of the CanvasAnimation class.
|
|
@@ -35,12 +32,11 @@ import { DragNDropYComponent } from '../dran-n-drop_helper/drag-n-drop-y.compone
|
|
|
35
32
|
|
|
36
33
|
*/
|
|
37
34
|
export class ChartAreaPanHandler extends ChartBaseElement {
|
|
38
|
-
constructor(bus, config, scale,
|
|
35
|
+
constructor(bus, config, scale, canvasInputListener, canvasBoundsContainer, canvasAnimation, chartPanComponent, hitTestCanvasModel) {
|
|
39
36
|
super();
|
|
40
37
|
this.bus = bus;
|
|
41
38
|
this.config = config;
|
|
42
39
|
this.scale = scale;
|
|
43
|
-
this.mainCanvasParent = mainCanvasParent;
|
|
44
40
|
this.canvasInputListener = canvasInputListener;
|
|
45
41
|
this.canvasBoundsContainer = canvasBoundsContainer;
|
|
46
42
|
this.canvasAnimation = canvasAnimation;
|
|
@@ -97,7 +93,6 @@ export class ChartAreaPanHandler extends ChartBaseElement {
|
|
|
97
93
|
// Continue redrawing hit test
|
|
98
94
|
this.hitTestCanvasModel.hitTestDrawersPredicateSubject.next(true);
|
|
99
95
|
};
|
|
100
|
-
this.touchHandler = new MainCanvasTouchHandler(this.scale, this.canvasInputListener, this.mainCanvasParent);
|
|
101
96
|
const allPanesHitTest = this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.ALL_PANES);
|
|
102
97
|
//#region drag-n-drop logic
|
|
103
98
|
const dragNDropXComponent = new DragNDropXComponent(allPanesHitTest, {
|
|
@@ -153,8 +148,6 @@ export class ChartAreaPanHandler extends ChartBaseElement {
|
|
|
153
148
|
.subscribe(({ prependedCandlesWidth }) => {
|
|
154
149
|
this.lastXStart += prependedCandlesWidth;
|
|
155
150
|
}));
|
|
156
|
-
this.touchHandler.activate();
|
|
157
|
-
this.addSubscription(this.touchHandler.deactivate.bind(this.touchHandler));
|
|
158
151
|
}
|
|
159
152
|
calculateDynamicSesitivity(e, maxSensitivity) {
|
|
160
153
|
// max delta distance that touchpad can provide
|
|
@@ -18,10 +18,4 @@ export declare class DragNDropXComponent extends DragNDropComponent {
|
|
|
18
18
|
* @returns {void}
|
|
19
19
|
*/
|
|
20
20
|
protected doActivate(): void;
|
|
21
|
-
/**
|
|
22
|
-
* This method overrides the doDeactivate method of the parent class and calls it using the super keyword.
|
|
23
|
-
* It is used to deactivate the current object and perform any necessary cleanup operations.
|
|
24
|
-
* @protected
|
|
25
|
-
*/
|
|
26
|
-
protected doDeactivate(): void;
|
|
27
21
|
}
|
|
@@ -22,12 +22,4 @@ export class DragNDropXComponent extends DragNDropComponent {
|
|
|
22
22
|
this.addRxSubscription(this.canvasInputListener.observeXDrag().subscribe(this.onDragTick));
|
|
23
23
|
this.addRxSubscription(this.canvasInputListener.observeXDragEnd().subscribe(this.onDragEnd));
|
|
24
24
|
}
|
|
25
|
-
/**
|
|
26
|
-
* This method overrides the doDeactivate method of the parent class and calls it using the super keyword.
|
|
27
|
-
* It is used to deactivate the current object and perform any necessary cleanup operations.
|
|
28
|
-
* @protected
|
|
29
|
-
*/
|
|
30
|
-
doDeactivate() {
|
|
31
|
-
super.doDeactivate();
|
|
32
|
-
}
|
|
33
25
|
}
|
|
@@ -15,9 +15,4 @@ export declare class DragNDropYComponent extends DragNDropComponent {
|
|
|
15
15
|
* @returns {void}
|
|
16
16
|
*/
|
|
17
17
|
protected doActivate(): void;
|
|
18
|
-
/**
|
|
19
|
-
* This method overrides the doDeactivate method of the parent class and calls the parent method before executing its own code.
|
|
20
|
-
* It is a protected method, which means it can only be accessed within the class and its subclasses.
|
|
21
|
-
*/
|
|
22
|
-
protected doDeactivate(): void;
|
|
23
18
|
}
|
|
@@ -19,11 +19,4 @@ export class DragNDropYComponent extends DragNDropComponent {
|
|
|
19
19
|
this.addRxSubscription(this.canvasInputListener.observeYDrag().subscribe(this.onDragTick));
|
|
20
20
|
this.addRxSubscription(this.canvasInputListener.observeYDragEnd().subscribe(this.onDragEnd));
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
23
|
-
* This method overrides the doDeactivate method of the parent class and calls the parent method before executing its own code.
|
|
24
|
-
* It is a protected method, which means it can only be accessed within the class and its subclasses.
|
|
25
|
-
*/
|
|
26
|
-
doDeactivate() {
|
|
27
|
-
super.doDeactivate();
|
|
28
|
-
}
|
|
29
22
|
}
|