Skip to content

Commit

Permalink
Pull request #5312: Feature/DXCF-5637 adaptive web crosshair behaviou…
Browse files Browse the repository at this point in the history
…r adjustments

Merge in DXCHARTS/dxchart5 from feature/DXCF-5637-adaptive-web-crosshair-behaviour-adjustments to master

* commit 'f11d7e0a1e475ad90dded22d139e42bdb835117b':
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // pr fix
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // remove copyrights
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // pr fix
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // pr fix
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // pr fix
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init
  [DXCF-5637] [Adaptive web] Crosshair behaviour adjustments // init

GitOrigin-RevId: c2ddd8dd81dd568972418a010d8eb78935b5cdd0
  • Loading branch information
Keelaro1 authored and dxcity committed Nov 19, 2024
1 parent 9941440 commit 12cebc9
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 46 deletions.
1 change: 1 addition & 0 deletions src/chart/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ export default class ChartBootstrap {
this.canvasBoundsContainer,
this.paneManager,
timeZoneModel,
chartPanComponent.mainCanvasTouchHandler,
formatterFactory,
);
this.chartComponents.push(this.hoverProducer);
Expand Down
8 changes: 7 additions & 1 deletion src/chart/components/cross_tool/cross-tool.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,17 @@ export class CrossToolComponent extends ChartBaseElement {
this.crossToolCanvasModel,
crossEventProducer,
hoverProducer,
this.canvasBoundsContainer,
);
this.addChildEntity(this.model);
const clearCanvasDrawer = new ClearCanvasDrawer(this.crossToolCanvasModel);
this.registerDefaultDrawerTypes();
const crossToolDrawer = new CrossToolDrawer(this.model, this.crossToolCanvasModel, this.crossToolTypeDrawers);
const crossToolDrawer = new CrossToolDrawer(
this.model,
this.config,
this.crossToolCanvasModel,
this.crossToolTypeDrawers,
);
const compositeDrawer = new CompositeDrawer();
compositeDrawer.addDrawer(clearCanvasDrawer, 'CLEAR_CANVAS');
compositeDrawer.addDrawer(crossToolDrawer, 'CROSS_TOOL_DRAWER');
Expand Down
8 changes: 6 additions & 2 deletions src/chart/components/cross_tool/cross-tool.drawer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { CanvasModel } from '../../model/canvas.model';
import { Drawer } from '../../drawers/drawing-manager';
import { CrossToolHover, CrossToolModel, CrossToolType } from './cross-tool.model';
import { FullChartConfig } from '../../chart.config';

export interface CrossToolTypeDrawer {
draw: (ctx: CanvasRenderingContext2D, hover: CrossToolHover) => void;
Expand All @@ -14,6 +15,7 @@ export interface CrossToolTypeDrawer {
export class CrossToolDrawer implements Drawer {
constructor(
private model: CrossToolModel,
private config: FullChartConfig,
private crossToolCanvasModel: CanvasModel,
private readonly crossToolTypeDrawers: Record<CrossToolType, CrossToolTypeDrawer>,
) {}
Expand All @@ -27,11 +29,13 @@ export class CrossToolDrawer implements Drawer {
* @returns {void}
*/
draw() {
const drawer = this.crossToolTypeDrawers[this.model.type];
const drawer = this.crossToolTypeDrawers[this.config.components.crossTool.type];
if (drawer) {
this.model.currentHover && drawer.draw(this.crossToolCanvasModel.ctx, this.model.currentHover);
} else {
console.error(`No cross tool drawer type registered for drawer type ${this.model.type}`);
console.error(
`No cross tool drawer type registered for drawer type ${this.config.components.crossTool.type}`,
);
}
}

Expand Down
63 changes: 53 additions & 10 deletions src/chart/components/cross_tool/cross-tool.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { CrossEventProducerComponent } from '../../inputhandlers/cross-event-pro
import { Hover, HoverProducerComponent } from '../../inputhandlers/hover-producer.component';
import { CanvasModel } from '../../model/canvas.model';
import { ChartBaseElement } from '../../model/chart-base-element';
import { CHART_UUID } from '../../canvas/canvas-bounds-container';
import { CanvasBoundsContainer, CanvasElement, CHART_UUID } from '../../canvas/canvas-bounds-container';
import { isMobile } from '../../utils/device/browser.utils';

export type CrossToolType = 'cross-and-labels' | 'only-labels' | 'none' | string;

Expand All @@ -29,16 +30,15 @@ export class CrossToolModel extends ChartBaseElement {
set currentHover(value: CrossToolHover | null) {
this.currentHoverSubject.next(value);
}
type: CrossToolType = 'cross-and-labels';

constructor(
private config: Required<ChartConfigComponentsCrossTool>,
private crossToolCanvasModel: CanvasModel,
private crossEventProducer: CrossEventProducerComponent,
private hoverProducer: HoverProducerComponent,
private canvasBoundsContainer: CanvasBoundsContainer,
) {
super();
this.type = config.type;
}

/**
Expand All @@ -48,21 +48,19 @@ export class CrossToolModel extends ChartBaseElement {
* @returns {void}
*/
public setType(type: CrossToolType) {
this.type = type;
this.config.type = type;
}

/**
* Method to activate the cross tool.
* It subscribes to the canvasInputListener's mouse move event and fires the draw event.
* It also subscribes to the eventBus's hover and close hover events and updates the hover and fires the draw event accordingly.
* It also subscribes to the chartModel's candlesSetSubject and timeZoneModel's observeTimeZoneChanged events and recalculates the cross tool X formatter.
* It subscribes to the hoverProducer's hover event and updates the crosstool.
*/
protected doActivate() {
super.doActivate();
this.addRxSubscription(
this.hoverProducer.hoverSubject.subscribe(hover => {
if (this.crossEventProducer.crossSubject.getValue() !== null && hover !== null) {
this.updateHover(hover);
isMobile() ? this.updateCrossToolMobile(hover) : this.updateCrossTool(hover);
} else {
this.currentHover = null;
}
Expand All @@ -76,7 +74,7 @@ export class CrossToolModel extends ChartBaseElement {
* @private
*/
private fireDraw() {
if (this.type !== 'none') {
if (this.config.type !== 'none') {
this.crossToolCanvasModel.fireDraw();
}
}
Expand All @@ -95,7 +93,7 @@ export class CrossToolModel extends ChartBaseElement {
* @param {number} hover.candleHover.closestOHLCY - The y coordinate of the closest OHLC price of the candle.
* @returns {void}
*/
public updateHover(hover: Hover, magnetTarget = this.config.magnetTarget) {
public updateCrossTool(hover: Hover, magnetTarget = this.config.magnetTarget) {
if (this.currentHover === null) {
this.currentHover = { x: hover.x, y: 0, time: hover.timeFormatted, paneId: hover.paneId };
} else {
Expand Down Expand Up @@ -129,4 +127,49 @@ export class CrossToolModel extends ChartBaseElement {
this.currentHover.paneId = hover.paneId;
this.currentHoverSubject.next(this.currentHover);
}

private updateCrossToolMobile(hover: Hover) {
// 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 = this.hoverProducer.createHover(x, y, hover.paneId) ?? hover;

const updatedHover = {
...crossToolHover,
x,
y,
};

this.crossEventProducer.crossToolHover = updatedHover;
this.updateCrossTool(updatedHover);
}
}
42 changes: 41 additions & 1 deletion src/chart/inputhandlers/cross-event-producer.component.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/*
* Copyright (C) 2019 - 2024 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/.
*/
/*
* Copyright (C) 2019 - 2024 Devexperts Solutions IE Limited
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
Expand All @@ -9,14 +14,47 @@ import { CanvasBoundsContainer, HitBoundsTest, HitBoundsTestOptionsPartial } fro
import { CanvasInputListenerComponent } from '../inputlisteners/canvas-input-listener.component';
import { ChartBaseElement } from '../model/chart-base-element';
import { Unsubscriber } from '../utils/function.utils';
import { Pixel } from '../model/scaling/viewport.model';
import { Hover } from './hover-producer.component';
import { isMobile } from '../utils/device/browser.utils';

/**
* [x, y, uuid - Unique identifier for the subscription]
*/
export type CrossEvent = [number, number, string];

interface CrossToolTouchInfo {
// the placement of crosstool when it's set after long touch and further moving happens
fixed: {
x: Pixel;
y: Pixel;
};
// // the placement of crosstool after touchMove and touchEnd happened
temp: {
x: Pixel;
y: Pixel;
};
// true after longTouch event, initial movement and touchEnd happen
isSet: boolean;
/**
* additional flag to determine ordinary and long taps
* crosstool shouldn't be hidden after longtouch event even if coordinates are the same
* becomes true after touchStart and false after longTouchStart
*/
isCommonTap: boolean;
}

export class CrossEventProducerComponent extends ChartBaseElement {
panesSubscriptions: Partial<Record<string, Subscription>> = {};
public crossSubject: BehaviorSubject<CrossEvent | null> = new BehaviorSubject<CrossEvent | null>(null);
// mobile specific crosstool hover and touch info
public crossToolHover: Hover | null = null;
public crossToolTouchInfo: CrossToolTouchInfo = {
fixed: { x: 0, y: 0 },
temp: { x: 0, y: 0 },
isSet: false,
isCommonTap: false,
};
constructor(
private canvasInputListener: CanvasInputListenerComponent,
private canvasBoundsContainer: CanvasBoundsContainer,
Expand Down Expand Up @@ -80,7 +118,9 @@ export class CrossEventProducerComponent extends ChartBaseElement {
const cross: CrossEvent = [point.x, point.y, uuid];
this.crossSubject.next(cross);
closeHoverFired = false;
} else {
}
// crosstool should be hidden if hovering nonpane only on desktop
if (!enter && !isMobile()) {
this.crossSubject.next(null);
closeHoverFired = true;
}
Expand Down
Loading

0 comments on commit 12cebc9

Please sign in to comment.